Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 1 | # Range Clauses |
| 2 | |
| 3 | Spec: http://golang.org/doc/go_spec.html#For_statements |
| 4 | |
| 5 | ## Summary |
| 6 | |
sue spence | cb617f8 | 2015-10-06 15:49:10 +0100 | [diff] [blame] | 7 | A range clause provides a way to iterate over an array, slice, string, map, or channel. |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 8 | |
| 9 | ## Example |
| 10 | |
Amos Wenger | 7f8db3b | 2015-11-21 00:56:26 +0100 | [diff] [blame] | 11 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 12 | for k, v := range myMap { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 13 | log.Printf("key=%v, value=%v", k, v) |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 14 | } |
| 15 | |
| 16 | for v := range myChannel { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 17 | log.Printf("value=%v", v) |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 18 | } |
| 19 | |
| 20 | for i, v := range myArray { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 21 | log.Printf("array value at [%d]=%v", i, v) |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 22 | } |
| 23 | ``` |
| 24 | |
| 25 | ## Reference |
| 26 | |
| 27 | If only one value is used on the left of a range expression, it is the 1st value in this table. |
| 28 | |
| 29 | | Range expression | 1st value | 2nd value (optional) | notes | |
| 30 | |:-----------------|:----------|:---------------------|:------| |
| 31 | | array or slice a ` [n]E `, ` *[n]E `, or ` []E ` | index ` i int ` | ` a[i] ` E | |
| 32 | | string s string type | index ` i int ` | rune ` int ` | range iterates over Unicode code points, not bytes | |
| 33 | | map m ` map[K]V ` | key ` k K ` | value ` m[k] ` V | |
| 34 | | channel c chan E | element ` e E ` | _none_ | |
| 35 | |
| 36 | ## Gotchas |
| 37 | |
| 38 | When iterating over a slice or map of values, one might try this: |
| 39 | |
Amos Wenger | 7f8db3b | 2015-11-21 00:56:26 +0100 | [diff] [blame] | 40 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 41 | items := make([]map[int]int, 10) |
| 42 | for _, item := range items { |
| 43 | item = make(map[int]int, 1) // Oops! item is only a copy of the slice element. |
| 44 | item[1] = 2 // This 'item' will be lost on the next iteration. |
| 45 | } |
| 46 | ``` |
| 47 | |
| 48 | The ` make ` and assignment look like they might work, but the value property of ` range ` (stored here as ` item `) is a _copy_ of the value from ` items `, not a pointer to the value in ` items `. The following will work: |
| 49 | |
Amos Wenger | 7f8db3b | 2015-11-21 00:56:26 +0100 | [diff] [blame] | 50 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 51 | items := make([]map[int]int, 10) |
| 52 | for i := range items { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 53 | items[i] = make(map[int]int, 1) |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 54 | items[i][1] = 2 |
| 55 | } |
| 56 | ``` |