for range 是golang特有的循环遍历语法,类似于C#里的foreach。
for range 也是我们日常开发使用到最多的遍历方式。
// 遍历 数组/切片
for index,value := range array{
...
}
// 遍历 map
for key,value := range maps{
...
}
// 变量channel
for value := range channel{
...
}
接下来我会有针对的说一下for range的使用
先看下面的演示代码及输出
type student struct {
Name string
Age int
}
func main() {
studs := []student{
{Name: "zhou", Age: 24},
{Name: "li", Age: 23},
{Name: "wang", Age: 22},
}
for i, stu := range studs {
fmt.Printf("index: %d,point: %p ",i,&i)
fmt.Printf("value: %+v,point: %p \n",stu,&stu)
}
}
这里可以看到我们的遍历输出的值都是正确的,是我们想要的答案。
但是,每次输出的index跟 value的内存地址是完全相同的.这里说明了 for range是对切片数据做值拷贝来遍历的。
所以大家可以这样理解, for range 等同于下面这种写法
var index int
var value int
for i:=0; i< len(array);i++{
index = i
value = array[i]
...
}
func main() {
stuMap := map[string]student{
"zhou":{Name: "zhou", Age: 24},
"li":{Name: "li", Age: 23},
"wang":{Name: "wang", Age: 22},
}
for k, stu := range stuMap {
fmt.Printf("key: %s,point: %p ",k,&k)
fmt.Printf("value: %+v,point: %p \n",stu,&stu)
}
}
结果输出符合预期。同样,每次输出的key跟 value的内存地址是相同的。
需要注意两种情况
func main() {
studs := []student{
{Name: "zhou", Age: 24},
{Name: "li", Age: 23},
{Name: "wang", Age: 22},
}
stuChan := make(chan student,3)
for _,stu := range studs{ //不打印索引,所以选择使用_匿名变量接受index
stuChan <- stu
}
close(stuChan)
for stu := range stuChan {
fmt.Printf("stu:%+v \n",stu)
}
}
func main() {
stuChan := make(chan student)
for stu := range stuChan {
fmt.Printf("stu:%+v \n",stu)
}
}
动态遍历是一种非常特殊的情况,一般也不会出现。
func main() {
studs := []student{
{Name: "zhou", Age: 24},
}
fmt.Printf("1 %p \n",&studs)
for _,stu := range studs{
fmt.Printf("2 %p \n",&studs)
studs = append(studs, stu)
}
fmt.Printf("3 %p \n",&studs)
fmt.Print(studs)
}
上面的演示是 一边遍历切片 一边往切片里添加数据。可能很多人第一反应会认为是死循环,但是程序是正常的结束了,并且没有报错。
for range在开始遍历时已经确认了循环的次数,所以不会因为新数据的添加影响循环。
到此结束。
有问题,或者建议请留言,谢谢。