How working defer in concurrency code in Golang

279 Views Asked by At

I have some code:

...
func Run(tasks []Task, n, m int) error {
    ...
    for i := 0; i < n; i++ {
        go func() {
            defer wg.Done()
            for t := range taskCh {
                if atomic.LoadInt32(&errCount) >= int32(m) {
                    return
                }

                if err := t(); err != nil {
                    atomic.AddInt32(&errCount, 1)
                }
            }
        }()
    }

    for _, t := range tasks {
        taskCh <- t
    }
    close(taskCh)
    wg.Wait()
    if atomic.LoadInt32(&errCount) >= int32(m) {
        err = ErrErrorsLimitExceeded
    }
    ...
}

and its work fine, but why its does not work when I writing operating close() wg.Wait and if... on the defer?

    ...
    defer func() {
        close(taskCh)
        wg.Wait()
        if atomic.LoadInt32(&errCount) >= int32(m) {
            err = ErrErrorsLimitExceeded
        }
    }()
    for i := 0; i < n; i++ {
    ...

when variable errCount = 0

1

There are 1 best solutions below

0
ont.rif On BEST ANSWER

It is golang limitation that you cannot change returned variables from defer functions. The correct way to do this is (pay attention to (err error) named return value):

package main

import "fmt"

func someFunction() (err error) {
    defer func() {
        err = fmt.Errorf("Some error")
    }()

    err = fmt.Errorf("Some other error")

    return
}

func main() {
    fmt.Println(someFunction())
}

https://goplay.tools/snippet/9fwcqTIwhow