ホームページ  >  記事  >  バックエンド開発  >  メインゴルーチン Golang のチャネルに沿って送信された最後の値を受信できません

メインゴルーチン Golang のチャネルに沿って送信された最後の値を受信できません

WBOY
WBOY転載
2024-02-09 11:33:09497ブラウズ

主 goroutine Golang 中无法接收沿通道发送的最后一个值

Golang のメイン goroutine は、チャネルを通じて送信された最後の値を受信できません。これは、チャネルが閉じられると、ゴルーチンは再び新しい値を受け取ることができないためです。代わりに、チャネル内のすべての値が受信されるまで、受信操作がブロックされます。これは、受信操作中に発生する可能性のあるデッドロック状況を回避するための Golang の設計上の選択です。したがって、潜在的な問題やエラーを避けるために、Golang プログラムを作成するときはこの点に特別な注意を払う必要があります。

質問内容

golangでのTCPポートスキャナについて。 2 つの実装。1 つ目は私のもので、2 つ目は golang 本からのものです。多くの読者が以前にテストしたように、2 番目の方法は 100% 実現可能であると仮定します。しかし、両方とも同じ問題を抱えているようです。 result チャネルで送信された最後の値が main コルーチン で受信できず、チャネルからの値を無限に待機することになります。にもかかわらず、実際には値が送信されます。 観察結果: ポート数が 21 未満の場合は期待どおりに動作しますが、ポート数が 1000 を超えると、受信されない量が約 10 に増加します。 私はなぜなのか理解していない。

書籍での実装

func worker(ports, results chan int) {
    for p := range ports {
        address := fmt.Sprintf("scanme.nmap.org:%d", p)
        conn, err := net.Dial("tcp", address)
        if err != nil {
            results <- 0
            fmt.Println("sent", p)
            continue
        }
        conn.Close()
        results <- p
        fmt.Println("sent", p)
    }
}

func main() {
    ports := make(chan int, 100)
    results := make(chan int)

    var openports []int

    for i := 0; i < cap(ports); i++ {
        go worker(ports, results)
    }

    go func() {
        for i := 1; i <= 50; i++ {
            ports <- i
        }
    }()

    for i := 0; i < 50; i++ {
        port := <-results // after 49 it gets stuck infinitely, never proceed further
        fmt.Println("received", port, i)
        if port != 0 {
            openports = append(openports, port)
        }
    }

    close(ports)
    close(results)

    sort.Ints(openports)

    fmt.Println(openports)

}

回避策

この問題は、net.Dialer

にタイムアウトを追加することで解決されました。 リーリー

以上がメインゴルーチン Golang のチャネルに沿って送信された最後の値を受信できませんの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。