gpt4 book ai didi

go - 与 channel 的双向通讯

转载 作者:行者123 更新时间:2023-12-01 21:16:58 25 4
gpt4 key购买 nike

在下面的代码中:

package main

import (
"fmt"
"io/ioutil"
"net/http"
)

func getPage(url string) (int, error) {
resp, err := http.Get(url)
if err != nil {
return 0, err
}

defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return 0, err
}

return len(body), nil
}

func getter(urlChan chan string, size chan int) {
url := <-urlChan
length, err := getPage(url)
if err == nil {
size <- length
urlChan <- url
}
}

func main() {
urls := []string{"http://www.google.com/", "http://www.yahoo.com",
"http://www.bing.com", "http://bbc.co.uk"}

sizeChan := make(chan int)
urlChan := make(chan string)

for _, url := range urls {
urlChan <- url
go getter(urlChan, sizeChan)
}

for i := 0; i < len(urls); i++ {
fmt.Printf("%s has length %d\n", <-urlChan, <-sizeChan)
}
}

我使用 urlChan双向,以了解给定大小( urlChan)计算得出的url( sizeChan)。

对于 getter()例程,在将第一个字符串参数 url设置为 urlChan之后,下面的输出显示挂起情况:
$ go install github.com/shamhub/cs61a
$
$
$ bin/cs61a

1)如何在 channel 上执行双向通信?

2)如何分析给定进程的例行程序状态?

最佳答案

正如其他人已经指出的,您可以更简单地解决此问题:

type sized struct {
url string
length int
err error
}

func sizer(url string, result chan<- sized, wg *sync.WaitGroup) {
defer wg.Done()
length, err := getPage(url)
result <- sized{url, length, err}
}

func main() {
urls := []string{"http://www.google.com/", "http://www.yahoo.com",
"http://www.bing.com", "http://bbc.co.uk"}

ch := make(chan sized)
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go sizer(url, ch, &wg)
}
go func() {
wg.Wait()
close(ch)
}()

for result := range ch {
if result.err != nil {
fmt.Printf("%s: %s\n", result.url, result.err)
} else {
fmt.Printf("%s: length = %d\n", result.url, result.length)
}
}
}

Complete example on playground, though it can't dial out, so not really useful there.

How to perform bi-directional communication on a channel?



你不能

好吧,这并非完全正确。让我们说相反:您不应该。

假设我们有一个 channel :
var ch chan T

对于某些T型

channel 本身就是天生的……好吧,我认为无方向性是正确的词:
  • 任何人都可以使用ch <- val
  • 将T类型的任何值放入 channel
  • 任何人都可以使用var <- ch
  • 从 channel 中取出任何类型T的值

    这显然不是单向的,但我认为称其为双向是令人误解的:它具有“将事物放入”一侧和“取出事物”一侧,两者都集中在一个 channel 实例中,但是该 channel 与任何 channel 实例都没有关联。特定用户。您可以沿任一方向将 channel 值复制到定向实例(请参见 What's the point of one-way channels in Go?),但实际上它们都只是对基础非定向 channel 对象的引用。1然后,您可以传递原始 channel 或单向化的副本。对任何用户,或将其中任何一个视为任何人都可以使用的“全局”(宽范围)变量。

    现在,我们添加两个实体,分别称为X和Y。如果缓冲了 ch channel ,则X和Y之一或两者都可以放入项目,然后A和B之一或两者都可以取出项目。项目将按其进入的顺序出现,从而序列化访问;如果 channel 已满,则尝试放入项目将被阻止;但项目不会专门从X转移到Y。特别是:
    // Y: paused or stopped

    // do this in X when ch is initially empty:
    ch <- T{}
    v := <-ch

    在此,X将一个零值的 T放入 channel ,然后将其取出。这不是定向的。 X获得了自己的数据。

    如果 channel 不为空,但也不为满,则X或Y都可以向其中添加某些内容(作为队列),然后从队列的最前面删除某些内容。但这只是将 channel 用作队列。 (请参阅 Is it possible to use Go's buffered channel as a thread-safe queue?)

    如果此队列具有某些它肯定缺乏的功能,则可以将单个队列用于某种双向通信(请参阅 Is two way comm possible using a single message queue in C)。但是它没有它们。如果您确实需要双向通信,那么答案很明显:使用两个队列。将一个队列(一个 channel )指定为X发送到Y channel ,将另一个队列指定为Y发送到X channel 。

    1可以通过 unsafe访问/恢复基础 channel ,但是除非您确切地知道自己在做什么,否则不要这样做。向您传递了单向实例的某人可能不希望您使用该 channel 的另一侧。

    关于go - 与 channel 的双向通讯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61684182/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com