为了账号安全,请及时绑定邮箱和手机立即绑定

goroutine 是创建深拷贝还是浅拷贝?

goroutine 是创建深拷贝还是浅拷贝?

Go
森林海 2022-01-17 20:11:57
var person struct {    name string    id   int    phone int}func main () {    var myTest person    //construct the variable     ...    go func() {        fmt.Println(myTest.name)    }()}goroutine 是否从主函数中深度复制变量“myTest”?如果我的 goroutine 是这样的:go func() {    time.Sleep(10 * time.Second)    fmt.Println(myTest.name)}这个 goroutine 休眠了 10 秒,那么当 main 函数在 10 秒内改变“myTest”的值时,goroutine 会做什么呢?
查看完整描述

2 回答

?
MYYA

TA贡献1868条经验 获得超4个赞

Go 中没有“深拷贝”的概念,一切都是按值传递的。

不,你的样本甚至不是一个浅拷贝你传递了一个指针(字符串的地址):

如果你改变myTest.name了main函数,那么你在改变之后再次打印它,你会看到它会改变,请看这个证明示例代码:


package main


import (

    "fmt"

    "sync"

    "time"

)


type person struct {

    name  string

    id    int

    phone int

}


var wg sync.WaitGroup


func main() {

    myTest := person{"Alex", 22, 123}

    fmt.Printf("%T : %[1]v %v\n", myTest.name, &myTest.name) // string : Alex 0xc042006740

    wg.Add(1)

    go func() {

        fmt.Printf("%T : %[1]v %v\n", myTest.name, &myTest.name) // string : Alex 0xc042006740

        time.Sleep(500 * time.Millisecond)

        fmt.Printf("%T : %[1]v %v\n", myTest.name, &myTest.name) // string : J 0xc042006740

        wg.Done()

    }()

    time.Sleep(100 * time.Millisecond)

    myTest.name = "J"

    wg.Wait()

}

首先person struct这样定义:


type person struct {

    name  string

    id    int

    phone int

}  

第二次使用sync.WaitGroup等待 goroutine 完成。


关于你的主要问题,你可以像这样自己测试:


package main


import (

    "fmt"

    "sync"

    "time"

)


type person struct {

    name  string

    id    int

    phone int

}


var wg sync.WaitGroup


func main() {

    myTest := person{"Alex", 22, 123}

    wg.Add(1)

    go func() {

        fmt.Printf("%T : %[1]v\n", myTest.name) // string : Alex

        time.Sleep(500 * time.Millisecond)

        fmt.Printf("%T : %[1]v\n", myTest.name) // string : J

        wg.Done()

    }()

    time.Sleep(100 * time.Millisecond)

    myTest.name = "J"

    wg.Wait()

}

因此,正如您在此示例中看到的name,主函数中的字符串内容更改反映到 goroutine,因此它不是副本。

如果您需要这样的复制调用:


package main


import (

    "fmt"

    "sync"

    "time"

)


type person struct {

    name  string

    id    int

    phone int

}


var wg sync.WaitGroup


func main() {

    myTest := person{"Alex", 22, 123}

    wg.Add(1)

    go func(name string) {

        fmt.Printf("%T : %[1]v\n", name) // string : Alex

        time.Sleep(500 * time.Millisecond)

        fmt.Printf("%T : %[1]v\n", name) // string : Alex

        wg.Done()

    }(myTest.name)

    time.Sleep(100 * time.Millisecond)

    myTest.name = "J"

    wg.Wait()

}


查看完整回答
反对 回复 2022-01-17
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

Go 中没有“深拷贝”的概念,一切都是按值传递的。


在您的实例中,这不是副本,您直接引用变量,如果您想要副本执行以下操作:


myTest := myTest

time.Sleep(10 * time.Second)

fmt.Println(myTest.name)


查看完整回答
反对 回复 2022-01-17
  • 2 回答
  • 0 关注
  • 172 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号