###### range-over-args.go
```go
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args[1:]
for i, arg := range args {
fmt.Println(i+1, arg)
}
}
```
```
$ go run range-over-args.go foo bar
1 foo
2 bar
```
## Slice
The program takes a slice of the default `Args` slice to skip over the first argument at index 0, which is always the full pathname of the command. The bracket notation below specifies taking a slice starting at index 1 until the end of `os.Args`. [^1]
If there is an element accessible at index 1 of the original slice, `os.Args`, it will now be accessible at index 0 of the new slice, assigned to `args`.
```go
args := os.Args[1:]
```
## Short Variable Declarations
The snippet demonstrates a *short variable declaration* [^2], a standard Go idiom used in place of a more verbose form or even separate declaration and assignment statements.
```go
// Instead of this...
var args []string
args = os.Args
// Or this...
var args []string = os.Args
// Or even this (type automatically inferred)...
var args = os.Args
// Use short variable declarations instead.
// Idiomatic, but only works inside of functions.
// Type automatically inferred.
args := os.Args
```
## Looping with the Range Clause
Go has only one looping construct and it's based on the `for` keyword.
In Go, the idiomatic way to loop over types that can be iterated (including standard arrays, slices, strings, maps, and channels) is to use a range clause, as shown In this snippet.
```go
for i, arg := range args {
fmt.Println(i+1, ": ", arg)
}
```
For arrays and slices, range yields two values for each element: the index and the element at that index. These values can be assigned to variables using short variable declaration syntax. In this example, they are assigned to `i` and `arg`, respectively.
## Discarding Values
A common idiom when the index value value of the yielded element itself isn't needed is to use `_` in place of a variable name for the assignment. This is because Go doesn't allow any declared name to go unused, so `_` provides the ability to indicate that discarding the value is intentional.
```go
// ignore the index value
for _, arg := range args {
fmt.Println(arg)
}
```
## Loop syntax in more detail
In general, for anything in Go that returns multiple values, you only need to use the underscore as a placeholder to skip a positional value so that you can correctly assign other remaining positional values to variables.
If you're not interested in any remaining values after a particular position, you don't need to do anything to ignore them.
For this example then, if you only need to declare `i` for the index variable, it isn't necessary to use an underscore to ignore the following value for the element:
```go
// ignore the element value
for i := range args {
fmt.Println(i+1, args[i])
}
```
If for some reason you simply wanted to loop based on the length of args, ignoring *all* values, you can simply dispense with range variable assignments altogether:
```go
i := 0
// ignore both the index and element values
for range args {
// Increment and decrement statement:
// i++ <==> i += 1 <==> i = i + 1
// i-- <==> i -= 1 <==> i = i - 1
// Can't be used in an expression.
// No pre-increment/decrement support.
i++
fmt.Println(i)
}
```
Or just use `for` all by itself:
```go
i := 0
for {
// Loop exit condition.
if i == len(args) {
break
}
fmt.Println(i+1, args[i])
i++
}
```
You can always use the basic (classic, canonical C-style) for loop with an *init* statement, *condition* expression, and *post* statement:
```go
for i := 0; i < len(args); i++ {
fmt.Println(i+1, args[i])
}
```
Any of the three clauses in the for loop can be omitted. Semicolons must still be present as placeholders, unless there is only a single clause, which must be the condition clause:
```go
i := 0
for i < len(args) {
fmt.Println(i+1, args[i])
i++
}
```
---
Next: [[7. Command Flags]]
[^1]: Slices are very efficient in Go. Internally, a slice is a small struct that points to the underlying array elements while tracking the start, length, and capacity of the slice.
[^2]: Also referred to as *short statement assignments*. Type is automatically inferred. Can only be used inside functions. See: https://go.dev/ref/spec#Short_variable_declarations