为了账号安全,请及时绑定邮箱和手机立即绑定

无法从通道获取值

无法从通道获取值

Go
慕盖茨4494581 2023-07-31 15:02:14
我向通道插入一些值。之后我尝试将其从通道中取出,但它没有取出任何值并退出。有人知道为什么吗?package mainimport (    "fmt")func main() {    c := make( chan string)    for _, s := range []string{"A", "B", "C"} {        fmt.Println( "input : ", s)        go func() {            c <- s         }()    }    close( c)    // recive    for i := range c {        fmt.Println("output", i)    }}期望输出input :  Ainput :  Binput :  Coutput : Aoutput : Boutput : C电流输出input :  Ainput :  Binput :  C
查看完整描述

2 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

在将值添加到通道中之前,您的通道可能已关闭(close在 goroutine 的第一行之前调用)。那么频道里当然就没有什么可读的了。您可以切换到缓冲通道,而不是使用 goroutine 在通道中添加值,如下所示:


package main

import (

    "fmt"

)

func main() {

    inputs := []string{"A", "B", "C"}

    c := make(chan string, len(inputs))

    for _, s := range inputs {

        fmt.Println( "input : ", s)

        c <- s 

    }

    close(c)

    // recive

    for i := range c {

        fmt.Println("output", i)

    }

}

或者您可以使用 WaitGroup,如下所示:


package main

import (

    "fmt"

    "sync"

)

func main() {

    var wg sync.WaitGroup

    inputs := []string{"A", "B", "C"}

    c := make(chan string)

    for _, s := range inputs {

        fmt.Println( "input : ", s)

        wg.Add(1)

        go func(s string) {

            c <- s

            wg.Done()

        }(s)

    }

    go func(){

        wg.Wait()

        close(c)

    }()


    // recive

    for i := range c {

        fmt.Println("output", i)

    }

}


查看完整回答
反对 回复 2023-07-31
?
红糖糍粑

TA贡献1815条经验 获得超6个赞

您的代码中有几件事需要注意。


第一个是s在闭包中使用 for 循环中的变量。


go func() {

            c <- s 

        }()

在这里,您可能会得到不一致的值,因为您不知道这些 goroutine 何时执行。据您所知,您最终可能会向通道写入三次“C”。如果你想将它与单独的 goroutine 一起使用,请像这样使用它:


go func(str string) {

                c <- str 

            }(s)

对于未从通道检索的值,通道会在从中检索任何内容之前关闭。你可以这样写:


package main

import (

    "fmt"

)

func main() {

    c := make( chan string)

    go func(){

      for _, s := range []string{"A", "B", "C"} {

        fmt.Println( "input : ", s)

        c <- s 

      }

      close( c)

    }()

    // recive

    for i := range c {

        fmt.Println("output", i)

    }

}

但即使这样也会给你这样的输出(甚至可能会有所不同):


input :  A

input :  B

output A

output B

input :  C

output C

为了获得您想要的输出,您可能需要使用缓冲通道和某种机制来防止读取,直到所有内容都写入通道。也许是这样的:


package main

import (

    "fmt"

    "sync"

)

func main() {

    c := make( chan string,3)

    var wg sync.WaitGroup

    wg.Add(3)

    for _, s := range []string{"A", "B", "C"} {

        fmt.Println( "input : ", s)

        c <- s 

    }



    go func(w *sync.WaitGroup){

      // recive

      for i := range c {

        fmt.Println("output", i)

        w.Done()

      }

    }(&wg)


    wg.Wait()

    close(c)

}


查看完整回答
反对 回复 2023-07-31
  • 2 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信