Golang小菜-for range

Golang小菜-for range

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的使用

1.遍历数组切片

先看下面的演示代码及输出

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)
	}
}

Golang小菜-for range_第1张图片

这里可以看到我们的遍历输出的值都是正确的,是我们想要的答案。

但是,每次输出的index跟 value的内存地址是完全相同的.这里说明了 for range是对切片数据做值拷贝来遍历的。

所以大家可以这样理解, for range 等同于下面这种写法

var index int
var value int
for i:=0; i< len(array);i++{
    index = i
    value = array[i]
    
    ...
}

2.遍历map

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)
	}
}

Golang小菜-for range_第2张图片

结果输出符合预期。同样,每次输出的key跟 value的内存地址是相同的。

3.遍历 channel

需要注意两种情况

3.1for range可以遍历已经关闭channel,并读出已经写入的数据

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)
	}
}

Golang小菜-for range_第3张图片

3.2for range遍历未关闭的channel且为空,会发生阻塞

func main() {
	stuChan := make(chan student)

	for stu := range stuChan {
		fmt.Printf("stu:%+v \n",stu)
	}
}

Golang小菜-for range_第4张图片

4.动态遍历

动态遍历是一种非常特殊的情况,一般也不会出现。

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)
}

Golang小菜-for range_第5张图片

上面的演示是 一边遍历切片 一边往切片里添加数据。可能很多人第一反应会认为是死循环,但是程序是正常的结束了,并且没有报错。

for range在开始遍历时已经确认了循环的次数,所以不会因为新数据的添加影响循环。

总结

  1. for range的遍历是值拷贝的,不要操作for range方法体里的 key,value的指针。
  2. 在大多数情况下不建议使用for range遍历channel,因为需要配合close,但是找不到合适的地方去close channel。
  3. for range在开始遍历时确认循环次数。
  4. for range返回值有一定的规律
    • 遍历数组切片返回index和value
    • 遍历map返回key和value
    • 遍历channel返回value
  5. 遍历时多返回值可以配合匿名变量(_)选择性接收。

 

到此结束。

有问题,或者建议请留言,谢谢。

你可能感兴趣的:(Golang开发,golang,go,for,range)