从频道返回错误

zer*_*ing 22 go

当我在Go中编写一个函数时,它应该返回一个值和一个错误

func createHashedPassword(password string) string, error {
    //code
}
Run Code Online (Sandbox Code Playgroud)

我想在goroutine中执行这个createHashedPassword,我想通过通道传递数据.
但我的问题是,我如何在这里或在goroutine中处理错误?

Jim*_*imB 39

将多个输出捆绑到结构中是很常见的,并通过单个通道将它们一起返回.

type Result struct {
    Message string
    Error error
}

ch := make(chan Result)
Run Code Online (Sandbox Code Playgroud)


Ian*_*vis 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)
}
Run Code Online (Sandbox Code Playgroud)


And*_*eKR 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
}
Run Code Online (Sandbox Code Playgroud)

并且这样称呼:

resultCh, errorCh := createHashedPasswordAsynchronously("mysecret")
select {
case result := <-resultCh:
    storeHashedPassword(result)
case err := <-errorCh:
    log.Println(err.Error())
}
Run Code Online (Sandbox Code Playgroud)

匿名结构

这是"匿名结构"方式,类似于@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)
}
Run Code Online (Sandbox Code Playgroud)


saw*_*ard 5

(因为我无法发表评论...)

我回应JimB所说的话:

type Result struct {
    Message string
    Error error
}

ch := make(chan Result)
Run Code Online (Sandbox Code Playgroud)

有两个单独的通道的麻烦,一个是结果,另一个是错误,据我所知,它不支持开箱即用的并发线程。

例如,您可能有两个线程同时发送数据,导致答复混乱。也就是说,您首先从线程1收到结果,但首先从线程2收到错误。

创建像JimB建议的新类型很容易,并且应该与goroutines一起很好地工作。