goroutine创建的是深拷贝还是浅拷贝?
Does goroutine create a deep copy or shallow copy?
var person struct {
name string
id int
phone int
}
func main () {
var myTest person
//construct the variable
...
go func() {
fmt.Println(myTest.name)
}()
}
goroutine 是否从 main 函数深度复制变量 "myTest"?
如果我的 goroutine 是这样的:
go func() {
time.Sleep(10 * time.Second)
fmt.Println(myTest.name)
}
这个 goroutine 睡眠 10 秒,那么当 main 函数在 10 秒内改变 "myTest" 的值时,goroutine 会做什么?
go中没有"deep copy"的概念,一切都是传值
在您的实例中,这不是副本,您直接引用变量,如果您想要副本,请执行以下操作:
myTest := myTest
time.Sleep(10 * time.Second)
fmt.Println(myTest.name)
go中没有"deep copy"的概念,一切都是传值
没有你的样本甚至不是浅拷贝你传递了一个指针(字符串地址):
如果您在 main
函数中更改 myTest.name
然后在更改后再次打印它,您会看到它会发生变化,请参阅此证明示例代码:
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()
}
并查看:
var person struct {
name string
id int
phone int
}
func main () {
var myTest person
//construct the variable
...
go func() {
fmt.Println(myTest.name)
}()
}
goroutine 是否从 main 函数深度复制变量 "myTest"?
如果我的 goroutine 是这样的:
go func() {
time.Sleep(10 * time.Second)
fmt.Println(myTest.name)
}
这个 goroutine 睡眠 10 秒,那么当 main 函数在 10 秒内改变 "myTest" 的值时,goroutine 会做什么?
go中没有"deep copy"的概念,一切都是传值
在您的实例中,这不是副本,您直接引用变量,如果您想要副本,请执行以下操作:
myTest := myTest
time.Sleep(10 * time.Second)
fmt.Println(myTest.name)
go中没有"deep copy"的概念,一切都是传值
没有你的样本甚至不是浅拷贝你传递了一个指针(字符串地址):
如果您在 main
函数中更改 myTest.name
然后在更改后再次打印它,您会看到它会发生变化,请参阅此证明示例代码:
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()
}
并查看: