字符串切片上的范围不一致

时间:2017-08-29 14:31:27

标签: for-loop go closures goroutine for-range

此代码:

import "fmt"
func main() {
    string_slice:=[]string{"a","b","c"}

    for _,s:=range string_slice{
        s="asd"
        fmt.Println(s)
    }
    fmt.Println(string_slice)
}

产生输出“c c c”,而代码为:

const Nit = (function(){

    //closure to store instances
    const instances = [];

    class Nit {

        constructor(nit){

            //class have only one property immutable
            //writeble false to make it explicity

            Object.defineProperty(this, 'nit', {
                value: nit,
                writable: false
            });

            //if an instance of this value already exists 
            //return the same reference

            if(!instances[this]){
                instances[this] = this;
                console.log(instances);
            }
            else{
                return instances[this];
            }

    }

    //valueOf garantee instances are comparable 
    //and interchangeable (because are immutable)

    Nit.prototype.valueOf = function(){
        return this.nit;
    };

    return Nit;

})();

产生输出“[a b c]”

第一个建议对范围迭代而不是引用(它不应该),第二个建议它迭代值的副本(它应该)。

为什么第一个产生输出“a b c”?

1 个答案:

答案 0 :(得分:0)

使用goroutine时,你必须假设它将以parallelo运行。所以在这种情况下可能会发生&#c c c'同样也是' b b'或者&a 39'

在此代码中运行3次:

for _,s:=range string_slice \\run t0, t1, t2 

将发送 3次此代码:

go func(){
  fmt.Println(s)
}()//send in t0, t1, t2

因此,根据示例,func()可能会在t2中开始运行。在这种情况下,结果将是&#39 c c'因为 s 等于最新值(string_slice [2])。

解决方案是func params的复制值:

for _, s := range string_slice{
    go func(x string){
        time.Sleep(1*time.Second)
        fmt.Println(x)
    }(s)
}

或者每次迭代创建新值

//creating new value per iteration
for i := range string_slice{
    s := string_slice[i]
    go func(){
        time.Sleep(1*time.Second)
        fmt.Println(s)
    }()
}

请参阅https://play.golang.org/p/uRD6Qy6xSw