2017-08-29 54 views
-2

此代碼:範圍超過串切片不一致

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

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

    time.Sleep(3*time.Second) 
} 

產生輸出 「CCC」,而此代碼:

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

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

產生輸出 「[ABC]」

的第一個建議範圍迭代引用(它不應該),第二個暗示它遍歷值的副本(它應該)。

爲什麼第一個產生輸出「a b c」?

+1

的工作是什麼,第二個點?你打印3次後,你只是打印整個切片。 https://play.golang.org/p/rNEGrgS3AT – mkopriva

+4

https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables –

+2

https://golang.org/ DOC/FAQ#closures_and_goroutines – JimB

回答

0

當使用goroutine時,您必須假設它將以平行方式運行。因此,在這種情況下,可能會出現「CCC」太「BBB」或

上運行3次這樣的代碼「AAA」:

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

將運行 3次這樣的代碼發送:

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

因此,可能發生func()開始在t2中運行,每個例子。在這種情況下,結果將'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