关于 Golang Go语言中 range 的使用

关于 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 方法或者单独起个数组记录需要删除的元素

#7 你这是 filter 的需求,可以参考这个 https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating,其实就是用切片而不是用数组,由于切片是共享同一个 “backing array”,所以不会有额外的消耗。

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 语言中不可或缺的一部分。

回到顶部