当我在Go中编写一个函数时,它应该返回一个值和一个错误,如
func createHashedPassword(password string) string, error {
//code
}
我想在goroutine中执行这个createHashedPassword,我想通过频道传递数据。
但我的问题是,我如何在这里或在goroutine中处理错误?
答案 0 :(得分:35)
将多个输出捆绑到结构中是很常见的,并通过单个通道将它们一起返回。
type Result struct {
Message string
Error error
}
ch := make(chan Result)
答案 1 :(得分:16)
您可以传入错误频道和结果频道。
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)
}
答案 2 :(得分:8)
以下是我的两种首选方式:
两个频道,包裹
这是“两个通道”的方式,但包装成一个函数,使其看起来类似于常见的模式:
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
}
并且这样称呼:
resultCh, errorCh := createHashedPasswordAsynchronously("mysecret")
select {
case result := <-resultCh:
storeHashedPassword(result)
case err := <-errorCh:
log.Println(err.Error())
}
匿名结构
这是“匿名结构”方式,类似于@saward的答案,但没有明确命名结构成员:
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)
}
答案 3 :(得分:4)
(因为我还不能发表评论......)
我回应JimB所说的话:
type Result struct {
Message string
Error error
}
ch := make(chan Result)
两个独立通道的问题,一个用于结果,另一个用于错误,是(据我所知),它不支持开箱即用的并发线程。
例如,您可以有两个线程同时发送数据,其中回复无序。也就是说,首先从线程1接收结果,但首先从线程2接收错误。很容易创建像JimB建议的新类型,并且应该与goroutines一起使用。