在 Go
中秉沼,for range
用來遍歷 slice, map, chan
等氧猬,使用頻率很高,但遍歷雖好用漠魏,卻很容易踩坑妄均,且看 demo
如下:
1. 只有一個返回值時,則第一個參數(shù)是 index
package main
import "fmt"
func main() {
s := []string{"a", "b", "c"}
// 只有一個返回值:則第一個參數(shù)是index
for v := range s {
fmt.Println(v)
}
// 兩個返回值
for i, v := range s {
fmt.Println(i, v)
}
}
輸出結果如下:
0
1
2
=============
0 a
1 b
2 c
2. 遍歷 map
為隨機序輸出禁熏,slice
為索引序輸出
package main
import "fmt"
func main() {
m := make(map[string]string)
m["aaa"] = "AAA"
m["bbb"] = "BBB"
m["ccc"] = "CCC"
m["ddd"] = "DDD"
m["eee"] = "EEE"
// range map 為隨機序輸出
for i, v := range m {
fmt.Println(i, v)
}
fmt.Println("==================")
s := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
// range slice 為索引序輸出
for i, v := range s {
fmt.Println(i, v)
}
}
輸出結果如下:
ddd DDD
eee EEE
aaa AAA
bbb BBB
ccc CCC
==================
0 aaa
1 bbb
2 ccc
3 ddd
4 eee
3. range v 是值拷貝瞧毙,且只會聲明初始化一次
package main
import "fmt"
func main() {
ParseStudent()
}
type student struct {
Name string
Age int
}
func ParseStudent() {
m := make(map[string]*student)
stus := []student{
{Name: "zhang", Age: 22},
{Name: "li", Age: 23},
{Name: "wang", Age: 24},
}
for _, stu := range stus {
// 都指向了同一個stu的內(nèi)存指針宙彪,為什么有巧?
// 因為 for range 中的 v 只會聲明初始化一次
// 不會每次循環(huán)都初始化,最后賦值會覆蓋前面的
fmt.Printf("%p\n", &stu)
// 1. bad
m[stu.Name] = &stu
// 2. good
/*newStu := stu
m[stu.Name] = &newStu*/
}
for i, v := range m {
fmt.Println(i, v)
}
}
輸出結果如下:
0xc00008e020
0xc00008e020
0xc00008e020
zhang &{wang 24}
li &{wang 24}
wang &{wang 24}
正確做法應該是:將 good
部分注釋打開男图,運行結果如下:
0xc00000c080
0xc00000c080
0xc00000c080
li &{li 23}
wang &{wang 24}
zhang &{zhang 22}
小結:for range
遍歷注意以上幾個小坑:
- 只有一個返回值時甜橱,則第一個參數(shù)是
index
; - 遍歷
map
為隨機序輸出览露,slice
為索引序輸出譬胎; -
range v
是值拷貝,且只會聲明初始化一次堰乔;
掌握以上幾點后脐恩,就讓我們愉快的使用range
吧~