关于 Golang Go语言中 range 的使用

发布于 1周前 作者 itying888 来自 Go语言

关于 Golang Go语言中 range 的使用

func main() {
var a []int
a = append(a, 1, 2)
for _, _ = range a {
a = append(a, 1)
}
fmt.Println(a)
}

这个时候 range 不会无限循环,说明 range 在循环之前就创建了 a 的副本,a 的改动不会影响 range 的执行。(这一段持不肯定态度)

然后

func main() {  
    var a []int  
    a = append(a, 1, 2, 3, 4, 5, 4, 6, 6)  
	for i, t := range a {  
        if t == 4 }  
            a = append(a[:i], a[i+1:]...)  
        }  
    }  
    fmt.Println(a)  
} 

如果 range 提前保存了 a 的副本,a 中含有两个 4,第一次可以正确删除 4,第二次删除 4 的时候 i 的值应该为 a 的副本中的下标,应该会删除错误的数字,但事实是 go 正确的删除了两个 4

有没有人给小弟解个惑,纠结半天了


更多关于关于 Golang Go语言中 range 的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

11 回复

dd

更多关于关于 Golang Go语言中 range 的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我们遇到什么困难,都不要怕,微笑着面对它,消除恐惧的最好办法就是面对恐惧,加油,奥利给!

你少了一句“坚持,才是胜利”

我记得 go range 的 value 是值引用,那 key 是不是也是这样

猜测:range 不是创建的副本,而是获取了长度

你这里的正确只是碰巧正确而已,你可以把 a = append(a, 1, 2, 3, 4, 5, 4, 6, 6) 改成 a = append(a, 1, 2, 3, 4, 4, 4, 6, 6) 试试。

而且根据 https://golang.org/ref/spec#For_statements 里的 “For statements with range clause” 的第一种情况的说明,range 并不会索引到数组或者切片,而是索引到数组或切片的元素。

而不会无线循环的原因来源于这一句:“The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated.”

我佛了, 我就随便测试一个结果还是碰巧对了,什么鬼运气,我去好好瞅瞅

那对于这种需求有什么优雅的解决方法没,现在能想到的只有自己写个 index 方法或者单独起个数组记录需要删除的元素

slice 其实就是一个 struct,range 语句会复制这个 struct,而不是存放元素的 array,所以修改 slice 只是修改另一个 struct,对 range 所用的 struct 没有影响。
但是两个 struct 可能用到同一个 array,也可能用不同的 array,因为 append 可能扩容
删除 slice 里的特定元素有好几种方法,具体看: https://github.com/golang/go/wiki/SliceTricks

在 Go 语言中,range 关键字是一种强大且灵活的工具,用于遍历数组、切片、映射(map)、字符串和通道(channel)。下面是对 range 在不同情况下的基本用法说明:

  1. 数组和切片

    nums := []int{1, 2, 3}
    for index, value := range nums {
        fmt.Println(index, value)
    }
    

    这里,index 是元素的索引,value 是对应的元素值。你也可以只获取索引或值,例如 for index := range numsfor value := range nums

  2. 映射(map)

    myMap := map[string]int{"a": 1, "b": 2}
    for key, value := range myMap {
        fmt.Println(key, value)
    }
    

    在映射中,key 是键,value 是对应的值。

  3. 字符串

    str := "hello"
    for index, runeValue := range str {
        fmt.Println(index, runeValue)
    }
    

    对于字符串,index 是字节索引,runeValue 是对应的 Unicode 码点(rune)。

  4. 通道(channel)

    ch := make(chan int, 3)
    ch <- 1
    ch <- 2
    close(ch)
    for value := range ch {
        fmt.Println(value)
    }
    

    在通道中,range 会一直读取直到通道被关闭。

range 使得遍历这些数据结构变得简单且直观,是 Go 语言中不可或缺的一部分。

回到顶部