【问题标题】:Why is the value passed into the channel not being printed out by fmt.Println?为什么传入通道的值没有被 fmt.Println 打印出来?
【发布时间】:2021-01-17 18:56:24
【问题描述】:
func main() {
    links := []string{
        "http://google.com",
        "http://amazon.com",
        "http://golang.org",
        "http://yahoo.com",
        "http://ebay.com",
    }

    c := make(chan string)

    for _, link := range links {
        testRequest(link, c)
    }
    msg := <-c
    fmt.Println(msg)
}
func testRequest(s string, c chan string) {
    _, err := http.Get(s)
    if err != nil {
        fmt.Println(s, "Is down presently")
        c <- "Something might be down"
        return
    }
    fmt.Println(s, "Is working perfectly")
    c <- "Working great!"
}

通道应该是一个引用类型,由于某种原因,该函数没有向通道传递任何内容,因为每次我运行代码时,它都会按预期打印出第一行,但程序不会停止运行,而且不执行 fmt.Println(channel) 所以我的假设是没有值被传递到通道,因为它应该是,有什么原因吗?

【问题讨论】:

  • 这里的问题是程序没有退出,也没有打印来自通道@MuffinTop的值
  • 糟糕,搞错了。程序阻塞发送到通道c。在发送方和接收方准备好之前,无缓冲通道c 上的通信不会继续进行。所有发送在单次接收之前执行。

标签: go pointers channel


【解决方案1】:

对于无缓冲通道,testRequests() 中的写入将在您从 main() 中的通道读取之前阻塞。你陷入了僵局。通常你应该得到一个错误,通常当所有的 goroutine 被阻塞时去计算。不知道你为什么不这样做。

你可能想在不同的 goroutine 中运行 testRequests():

package main

import (
    "fmt"
    "net/http"
)

func main() {
    links := []string{
            "http://google.com",
            "http://amazon.com",
            "http://golang.org",
            "http://yahoo.com",
            "http://ebay.com",
    }

    c := make(chan string)

    go func() {
            for _, link := range links {
                    testRequest(link, c)
            }
            close(c)
    }()
    for msg := range c {
            fmt.Println(msg)
    }
    fmt.Println("Done handling request")
}

func testRequest(s string, c chan string) {
    _, err := http.Get(s)
    if err != nil {
            fmt.Println(s, "Is down presently")
            c <- "Something might be down"
            return
    }
    fmt.Println(s, "Is working perfectly")
    c <- "Working great!"
}

https://play.golang.org/p/g9X1h_NNJAB

【讨论】:

  • 当你发出一个 HTTP 请求时,HTTP 传输会创建一个或两个 goroutine 用于管理任务(通常是休眠,但不会无限阻塞),这足以让死锁检测器相信一切正常。这远非万无一失:)
  • 啊,这很有意义。我看到它恐慌的地方我没有任何http请求。谢谢@hobbs!
【解决方案2】:

你的程序在for第一个循环后卡住了,发送方尝试发送到通道但接收方只有在循环完成后才能接收

//This loop will blocks until finished
for _, link := range links {
    testRequest(link, c) // Try to send, receiver can't receive
}

//Until above loop finishs, this never excutes
msg := <-c
mt.Println(msg)

使用go 运行发送者循环,以便接收者循环可以执行,但您需要防止主程序退出,直到所有工作完成。

func main() {
    links := []string{
        "http://google.com",
        "http://amazon.com",
        "http://yahoo.com",
        "http://ebay.com",
    }

    c := make(chan string)

    // This code will not blocks
    go func() {
        for _, link := range links {
            testRequest(link, c)
        }
    }()

    // Above code doesn't block, this code can excutes
    for {
        msg := <-c
        fmt.Println(msg)
    }
}

func testRequest(s string, c chan string) {
    _, err := http.Get(s)
    if err != nil {
        fmt.Println(s, "Is down presently")
        c <- "Something might be down"
        return
    }
    fmt.Println(s, "Is working perfectly")
    c <- "Working great!"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多