Ответ 1
Обычно для объединения нескольких выходов в структуру и возврата их вместе по одному каналу.
type Result struct {
Message string
Error error
}
ch := make(chan Result)
Когда я пишу функцию в Go, она должна вернуть значение и ошибку, например
func createHashedPassword(password string) string, error {
//code
}
Я хочу выполнить это createHashedPassword в goroutine, и я думаю, чтобы передавать данные через канал.
Но мой вопрос: как я могу обрабатывать ошибку здесь или в goroutine?
Обычно для объединения нескольких выходов в структуру и возврата их вместе по одному каналу.
type Result struct {
Message string
Error error
}
ch := make(chan Result)
Вы можете передать канал ошибки, а также канал результата.
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)
}
Вот мои два предпочтительных способа:
Два канала, завернутые
Это способ "двух каналов", но заключенный в функцию, чтобы он выглядел аналогично общему шаблону:
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)
}
(так как я еще не могу прокомментировать...)
Я повторяю, что сказал JimB:
type Result struct {
Message string
Error error
}
ch := make(chan Result)
Проблема с двумя отдельными каналами, одна для результата и другая для ошибки, заключается в том, что (как я понимаю) он не будет поддерживать параллельные потоки из коробки.
Можно, например, иметь два потока, отправляющих данные одновременно, где ответы выходят из строя. То есть, сначала вы получаете результат из потока 1, но сначала ошибку из потока 2.
Легко создавать новые типы, такие как JimB, и хорошо работать с goroutines.