lakeIn231
lakeIn231

Reputation: 1315

how to return values in a goroutine

I have the code:

    go s.addItemSync(ch, cs.ResponseQueue, user)

This calls the func:

func (s *Services) addItemSync(ch types.ChannelInsertion, statusQueueName, user string) {
   //func body here
}

I would however like to do this:

if ok, err := go s.addItemSync(ch, cs.ResponseQueue, user); !ok {
    if err != nil {
        log.Log.Error("Error adding channel", zap.Error(err))
        return
}

Which would change the other func to this

func (s *Services) addItemSync(ch types.ChannelInsertion, statusQueueName, user string) (bool, error) {

}

As in, I would like to be able to declare a go func but this errors out every time. Any idea how you can declare a variable while able to call the go func ability for synchronous calls? as seen in the if ok, err := go s.addItemSync(ch, cs.ResponseQueue, user); !ok { line?

Upvotes: 0

Views: 5221

Answers (1)

PassKit
PassKit

Reputation: 12591

If you want to wait until a go-routine has completed, you need to return results in a channel. The basic pattern, without complicating with wait groups, etc. is:

func myFunc() {
    // make a channel to receive errors
    errChan := make(chan error)

    // launch a go routine
    go doSomething(myVar, errChan)

    // block until something received on the error channel
    if err := <- errChan; err != nil {
        // something bad happened
    }
}

// your async funciton
func doSomething(myVar interface{}, errChan chan error) {
    // Do stuff
    if something, err := someOtherFunc(myVar); err != nil {
         errChan <- err
         return
    }

    // all good - send nil to the error channel
    errChan <- nil

}

In your case if you just want to fire off a go-routine and log if an error happens, you can use an anonymous function:

go func() {
    if ok, err := s.addItemSync(ch, cs.ResponseQueue, user); !ok {
        if err != nil {
            log.Log.Error("Error adding channel", zap.Error(err))
        }
    }
}()

Or if you want to wait for the result:

errChan := make(chan error)
go func() {
    if ok, err := s.addItemSync(ch, cs.ResponseQueue, user); !ok {
        if err != nil {
            errChan <- err
            return
        }
    }
    errChan <- nil
}()

// do some other stuff while we wait...

// block until go routine returns
if err := <- errChan; err != nil {
    log.Log.Error("Error adding channel", zap.Error(err))
}

Note: Your code as written, may have unexpected results if it is possible that a response where ok == false would not return an error. If this is a concern, I would suggest creating and returning a new error for cases where !ok && err == nil

Upvotes: 6

Related Questions