The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Yooloo

关于 Golang 中 range 的使用

  •  
  •   Yooloo · Oct 24, 2019 · 3787 views
    This topic created in 2396 days ago, the information mentioned may be changed or developed.
    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

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

    Supplement 1  ·  Oct 24, 2019
    a = append(a, 1, 2, 3, 4, 4, 4, 6, 6)

    三个 4 就会错了,我太难了
    xta
        1
    xta  
       Oct 24, 2019   ❤️ 1
    dd
    Yooloo
        2
    Yooloo  
    OP
       Oct 24, 2019   ❤️ 2
    我们遇到什么困难,都不要怕,微笑着面对它,消除恐惧的最好办法就是面对恐惧,加油,奥利给!
    LG3xFA6kpn88HxEW
        3
    LG3xFA6kpn88HxEW  
       Oct 24, 2019
    @KaynW 你少了一句“坚持,才是胜利”
    FinnBai
        4
    FinnBai  
       Oct 24, 2019
    我记得 go range 的 value 是值引用,那 key 是不是也是这样

    猜测:range 不是创建的副本,而是获取了长度
    maichael
        5
    maichael  
       Oct 24, 2019   ❤️ 2
    你这里的正确只是碰巧正确而已,你可以把 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.”
    Yooloo
        6
    Yooloo  
    OP
       Oct 24, 2019
    @maichael 我佛了, 我就随便测试一个结果还是碰巧对了,什么鬼运气,我去好好瞅瞅
    Yooloo
        7
    Yooloo  
    OP
       Oct 24, 2019
    @maichael 那对于这种需求有什么优雅的解决方法没,现在能想到的只有自己写个 index 方法或者单独起个数组记录需要删除的元素
    maichael
        8
    maichael  
       Oct 24, 2019   ❤️ 2
    @KaynW #7 你这是 filter 的需求,可以参考这个 https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating,其实就是用切片而不是用数组,由于切片是共享同一个 “backing array”,所以不会有额外的消耗。
    reus
        10
    reus  
       Oct 24, 2019
    slice 其实就是一个 struct,range 语句会复制这个 struct,而不是存放元素的 array,所以修改 slice 只是修改另一个 struct,对 range 所用的 struct 没有影响。
    但是两个 struct 可能用到同一个 array,也可能用不同的 array,因为 append 可能扩容
    删除 slice 里的特定元素有好几种方法,具体看: https://github.com/golang/go/wiki/SliceTricks
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2953 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 47ms · UTC 05:31 · PVG 13:31 · LAX 22:31 · JFK 01:31
    ♥ Do have faith in what you're doing.