mgoldwasser
mgoldwasser

Reputation: 15434

Modifying a struct in a goroutine?

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

Upvotes: 0

Views: 2472

Answers (1)

janos
janos

Reputation: 124666

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

Upvotes: 5

Related Questions