php中文网

Go 语言中,当 context 被取消后,`

php中文网

上下文取消后,

在 go 语言中,使用 context.context 包可以实现协程间通信和取消。当 context 被取消后,

这是因为

导致该问题的一个示例

以下代码演示了该问题:

package main

import (
    "context"
    "fmt"
)

func gen(ctx context.context) <-chan interface{} {
    ch := make(chan interface{})
    go func() {
        n := 0
        for {
            select {
            case <-ctx.done():
                fmt.println("done")
            default:
                n += 1
                ch <- n
            }
        }

    }()
    return ch
}

func main() {
    ctx, cancel := context.withcancel(context.background())

    for n := range gen(ctx) {
        fmt.println(n)
        if n == 5 {
            break
        }
    }
    defer cancel()
}

在这种情况下,for循环将在读取到第六个元素之前一直运行。这意味着,当cancel()被调用时,第六个元素已经准备好了。因此,

解决方法

可以通过关闭通道来解决此问题。当上下文被取消时,关闭通道将导致

以下代码显示了改进后的示例:

package main

import (
    "context"
    "fmt"
)

func gen(ctx context.Context) <-chan interface{} {
    ch := make(chan interface{})
    go func() {
        n := 0
        for {
            select {
            case <-ctx.Done():
                fmt.Println("done")
                close(ch) // 关闭通道,range结束
                return
            default:
                n += 1
                ch <- n
            }
        }

    }()
    return ch
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())

    for n := range gen(ctx) {
        fmt.Println(n)
        if n == 5 {
            cancel()
            // break不能break,否则没有从ch中读取,就会一直阻塞在ch<-n
        }
    }
}

这样,无论第六个元素是否已经准备好,

以上就是Go 语言中,当 context 被取消后,`的详细内容,更多请关注php中文网其它相关文章!