不少时候须要将遍历对象中去掉某些元素,或者往遍历对象中添加元素,这时候就须要当心操做了。
对于go语言中的一些注意事项我作了总结和示例,留下点笔记。html
func main() { arr := []int{1, 2, 3, 4} for i := range arr { if arr[i] == 3 { arr = append(arr[:i], arr[i+1:]...) } } fmt.Println(arr) }
最终报错
panic: runtime error: index out of range [3] with length 3
,由于range在迭代时已经肯定i的范围为[0,len(arr))的左闭右开的区间。
可是当知足arr[i] == 3
时对arr进行了修改,缩短了arr的长度,此时len(arr)=3,最大下标为2,所以当执行arr[3]时会报错。golang
func main() { arr := []int{1, 2, 3, 4} for i, v := range arr { fmt.Println(i, v) if v == 3 { arr = append(arr[:i], arr[i+1:]...) // arr = []int{4, 5, 6, 7} // 能够将上一行代码替换,看最终遍历的i,v状况 } } fmt.Println(arr) }
仍是回到range的用法,当执行for循环时就已经肯定(i,v)的遍历元素值,及时循环过程当中修改arr,也不会改变for要遍历的(i,v)值。
能够将上面代码修改一下,看下在循环中改变arr值时,后面遍历的(i,v)是不会随着arr的改变而改变的。c#
func main() { arr := []int{1, 2, 3, 4} for i := 0; i < len(arr); i++ { fmt.Println(i, arr[i]) if arr[i] == 3 { arr = append(arr[:i], arr[i+1:]...) i-- } } fmt.Println(arr) }
该方案只修改i的值,在删除元素时进行i--,能够确保遍历arr没有问题,并且每次经过arr[i]获取切片值不存在问题。
固然用该方式也能够在遍历时添加元素,只要i也对应变化就没问题。缓存
for key := range m { if key.expired() { delete(m, key) } }
m = make(map[int]int) // 能够产生一个新对象,旧对象等着被垃圾回收 for k := range m { delete(m,k) // 循环遍历并删除map全部元素,好处是map缓存还在,下次添加时可直接使用缓存 }
关于切片遍历时进行操做须要注意一些坑。
关于map遍历时进行操做相对坑少点,不过遍历map须要修改元素时,map的value要为指针类型,这点得谨记。安全