Return error from the channel
You can pass in an error channel as well as a result channel.
errors := make(chan error, 0)
results := make(chan string, 0)
password := "test"
go func() {
result, err := createHashedPassword(string password)
if err != nil {
errors <- err
return
}
results <- result
}()
// do something else
// When you are ready to read from goroutine do this:
select {
case err := <- errors:
println(err)
case res := <- results:
println(res)
}
It's common to bundle multiple outputs into a struct, and return them together over a single channel.
type Result struct {
Message string
Error error
}
ch := make(chan Result)
Here are my two preferred ways:
Two channels, wrapped
This is the "two channels" way, but wrapped into a function to make it look similar to the common pattern:
func createHashedPasswordAsynchronously(password string) (chan string, chan error) {
resultCh := make(chan string)
errorCh := make(chan error)
go func(password string) {
//code
if err != nil {
errorCh <- errors.New("Does not compute")
} else {
resultCh <- "8badf00d"
}
}(password)
return resultCh, errorCh
}
And called like this:
resultCh, errorCh := createHashedPasswordAsynchronously("mysecret")
select {
case result := <-resultCh:
storeHashedPassword(result)
case err := <-errorCh:
log.Println(err.Error())
}
Anonymous struct
This is the "anonymous struct" way, similar to @saward's answer, but without naming the struct members explicitly:
go func(password string, ch chan struct {
string
error
}) {
//code
if err != nil {
ch <- struct {
string
error
}{"", errors.New("Does not compute")}
} else {
ch <- struct {
string
error
}{"8badf00d", nil}
}
}("mysecret", ch)
r := <-ch
if r.error != nil {
log.Println(r.error.Error())
} else {
storeHashedPassword(r.string)
}
(since I cannot comment yet...)
I echo what JimB said with:
type Result struct {
Message string
Error error
}
ch := make(chan Result)
The trouble with two separate channels, one for the result, and another for the error, is that (as I understand) it won't support concurrent threads out of the box.
You could, for example, have two threads sending data at the same time, where the replies get out of order. That is, you receive the result from thread 1 first, but the error from thread 2 first.
It's easy to create new types like JimB suggested, and should work well with goroutines.