Search code examples
loopsgogoroutine

Pass a result from goroutine to a variable inside the loop


At the code below how to assign a result from slowExternalFunction to a proper person? It can be done via channels and just for clarity I defined that slowExternalFunction returns int.

type Person struct {
    Id        int
    Name      string
    WillDieAt int
}

func slowExternalAPI(i int) int {
    time.Sleep(10)
    willDieAt := i + 2040
    return willDieAt 
}

func fastInternalFunction(i int) string {
    time.Sleep(1)
    return fmt.Sprintf("Ivan %v", i)
}

func main() {
    var persons []Person

    for i := 0; i <= 100; i++ {
        var person Person
        person.Id = i
        person.Name = fastInternalFunction(i)
        go slowExternalAPI(i)
        person.WillDieAt = 2050 //should be willDieAt from the slowExternalAPI
        persons = append(persons, person)
    }
    fmt.Printf("%v", persons)
}

https://play.golang.org/p/BRBgtH5ryo


Solution

  • To do it using channels you'll have to refactor your code quite a bit.

    Smallest change would be to do the assignment in the goroutine:

    go func(){
        person.WillDieAt = slowExternalFunction(i)
    }()
    

    However, to make this work we'd need to make some other changes as well:

    • Use an array of pointers so that you can add the person before the assignment finishes.
    • Implement a wait group so that you wait for all goroutines to finish before printing the results.

    Here's the complete main function with the changes:

    func main() {
        var persons []*Person
        var wg sync.WaitGroup
    
        for i := 0; i <= 100; i++{
            person := &Person{}
            person.Id = i
            person.Name = fastInternalFunction(i)
            wg.Add(1)
            go func(){
                person.WillDieAt = slowExternalFunction(i)
                wg.Done()
            }()
    
            persons = append(persons,person)
        }
        wg.Wait()
        for _, person := range persons {
            fmt.Printf("%v ", person )
        }
    }
    

    Playground: https://play.golang.org/p/8GWYD29inC