Modifying a struct in a goroutine?

huangapple go评论82阅读模式
英文:

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)
}

huangapple
  • 本文由 发表于 2017年3月11日 20:53:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/42735444.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定