英文:
Modifying a struct in a goroutine?
问题
我正在翻译以下内容:
我正在尝试使用goroutines进行实验,但似乎无法在goroutine中修改结构体的值(如下面的示例)。有没有解决这个问题的方法?
编辑:如果我加入一个sleep语句,代码似乎可以运行,这表明如果给予足够的时间,goroutine会运行,但它们在main()中的所有内容执行完毕后才完成运行。在继续之前,如何“等待”goroutine完成?
package main
import (
"fmt"
)
type num struct {
val int
}
func (d *num) cube_val() {
fmt.Println("changing value...")
d.val = d.val * d.val * d.val
}
func main() {
a := []num{num{1}, num{3}, num{2}, num{5}, num{4}}
for i := range a {
go a[i].cube_val()
}
// 在这里插入等待goroutine完成的代码...
fmt.Println(a) // 改变不会发生
for i := range a {
a[i].cube_val()
}
fmt.Println(a) // 改变发生了,并且fmt.Println语句起作用?
}
英文:
I was experimenting with goroutines, and it seems I can't modify the value of a struct within a goroutine (example below). Is there any work around for this?
EDIT: It appears that the code runs if I place a sleep statement, indicating that the goroutines would run if given more time, but they finish running after everything in main() has already executed. How do I "wait" for my goroutines to finish before proceeding?
package main
import (
"fmt"
)
type num struct {
val int
}
func (d *num) cube_val() {
fmt.Println("changing value...")
d.val = d.val*d.val*d.val
}
func main() {
a := []num{num{1},num{3},num{2},num{5},num{4}}
for i := range a {
go a[i].cube_val()
}
// code that waits for go routines to finish should get inserted here ...
fmt.Println(a) // change does NOT happen
for i := range a {
a[i].cube_val()
}
fmt.Println(a) // change happens, and fmt.Println statements worked?
}
答案1
得分: 5
变化确实发生了。但是它们发生在fmt.Println(a)
之后。实际上,在没有同步的情况下,无法保证goroutine和打印语句的执行顺序。
如果你希望fmt.Println(a)
在goroutine完成后发生,你需要等待它们完成,例如:(在Playground上查看1)
func main() {
var wg sync.WaitGroup
a := []num{num{1}, num{3}, num{2}, num{5}, num{4}}
for i := range a {
wg.Add(1)
go func(d *num) {
defer wg.Done()
d.cube_val()
}(&a[i])
}
wg.Wait()
fmt.Println(a)
}
英文:
The changes do happen. But they happened for you after the fmt.Println(a)
.
In fact there are no guarantees on the execution order of the goroutines and the print statement, without synchronization.
If you want the fmt.Println(a)
happen after the goroutines have completed, you have to wait for them, for example: (see also on Playground)
func main() {
var wg sync.WaitGroup
a := []num{num{1}, num{3}, num{2}, num{5}, num{4}}
for i := range a {
wg.Add(1)
go func(d *num) {
defer wg.Done()
d.cube_val()
}(&a[i])
}
wg.Wait()
fmt.Println(a)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论