字符串切片的范围不一致

Posted

技术标签:

【中文标题】字符串切片的范围不一致【英文标题】:Range over string slice is inconsistent 【发布时间】:2018-02-07 01:39:17 【问题描述】:

这段代码:

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)

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

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

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

产生输出“[a b c]”

第一个建议 for range 迭代引用(它不应该),第二个建议它迭代值的副本(它应该)。

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

【问题讨论】:

第二个有什么意义?在打印"asd" 3 次后,您只是在打印整个切片。 play.golang.org/p/rNEGrgS3AT github.com/golang/go/wiki/… golang.org/doc/faq#closures_and_goroutines 【参考方案1】:

当使用 goroutine 时,你必须假设它会并行运行。所以在这种情况下可能会出现 'c c c' as too 'b b b' 或 'a a a'

在此代码运行 3 次时:

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

将发送运行 3 次此代码:

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

因此,例如,func() 可能会在 t2 开始运行。在这种情况下,结果将是 'c 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工作

【讨论】:

以上是关于字符串切片的范围不一致的主要内容,如果未能解决你的问题,请参考以下文章

为啥 pandas 多索引数据帧切片看起来不一致?

当 j 有时为 0 时,如何避免不一致的 s[i:-j] 切片行为?

偶然发现getline、fstream、范围不一致

Ocaml中“type ...and”和“let ...and”之间的范围不一致

Python12 切片迭代

在 c# 中,隐式短到字节是不可能的,但在隐式 int 到短时没有问题。源值始终与目标范围一致