2 回答

TA貢獻(xiàn)1784條經(jīng)驗(yàn) 獲得超9個(gè)贊
正如其他人已經(jīng)指出的那樣,您可以更簡(jiǎn)單地解決這個(gè)問題:
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)
}
}
}
操場(chǎng)上的完整示例,雖然它不能撥出,所以在那里不是很有用。
如何在通道上進(jìn)行雙向通信?
你不能。
嗯,這并不完全正確。讓我們說:你不應(yīng)該.
假設(shè)我們有一個(gè)頻道:
var ch chan T
對(duì)于某些類型 T。
頻道本身是天生的......好吧,我認(rèn)為非定向是正確的詞:
任何人都可以將任何類型 T 的值放入通道中ch <- val
任何人都可以從通道中取出任何類型 T 的值var <- ch
這顯然不是單向的,但我認(rèn)為稱其為雙向是一種誤導(dǎo):它有一個(gè)“放入”一側(cè)和一個(gè)“取出”一側(cè),兩者都集中在一個(gè)通道實(shí)例中,但該通道與任何通道都沒有關(guān)聯(lián)特定用戶。您可以在任一方向上將通道值復(fù)制到有向?qū)嵗ㄕ?qǐng)參閱Go 中單向通道的意義何在?),但兩者實(shí)際上都只是對(duì)底層非定向通道對(duì)象的引用。1 然后,您可以將原始通道或其單向化副本傳遞給任何用戶,或?qū)⑵渲腥魏我粋€(gè)視為任何人都可以使用的“全局”(寬范圍)變量。
現(xiàn)在讓我們添加兩個(gè)實(shí)體,我們將其稱為 X 和 Y。如果 channelch是buffered,則 X 和 Y 中的一個(gè)或兩個(gè)可以放入項(xiàng)目,然后 A 和 B 中的一個(gè)或兩個(gè)可以取出項(xiàng)目。項(xiàng)目將按照進(jìn)入的順序出現(xiàn),序列化訪問;如果通道已滿,則嘗試將項(xiàng)目放入將被阻止;但項(xiàng)目不會(huì)專門從X轉(zhuǎn)移到Y(jié)。特別是:
// Y: paused or stopped
// do this in X when ch is initially empty:
ch <- T{}
v := <-ch
在這里,X 將一個(gè)零值T放入通道,然后將其取出。這不是定向的。X 取回了自己的數(shù)據(jù)。
如果通道不是空的,也不是滿的,X 或 Y 可以向它添加一些東西(作為一個(gè)隊(duì)列),然后從隊(duì)列的前面取出一些東西。但這只是將通道用作隊(duì)列。(參見Is it possible to use Go's buffered channel as a thread-safe queue?)
如果此隊(duì)列具有它肯定缺少的某些功能,您可以使用單個(gè)隊(duì)列進(jìn)行雙向通信(請(qǐng)參閱Is two way comm possible using a single message queue in C)。但它沒有它們。如果真的需要雙向通信,答案很明顯:使用兩個(gè)隊(duì)列。指定一個(gè)隊(duì)列(一個(gè)通道)作為 X-sends-to-Y 通道,另一個(gè)作為 Y-sends-to-X 通道。

TA貢獻(xiàn)1765條經(jīng)驗(yàn) 獲得超5個(gè)贊
你必須閱讀并練習(xí) go tour,我相信下面代碼中使用的每個(gè)細(xì)節(jié)都會(huì)在那里解釋,但是,這是一個(gè)解決方案
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
)
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
}
type result struct {
url string
len int
err error
}
func main() {
urls := []string{"http://www.google.com/", "http://www.yahoo.com",
"http://www.bing.com", "http://bbc.co.uk"}
resChan := make(chan result)
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go func(url string) {
defer wg.Done()
l, err := getPage(url)
resChan <- result{url: url, len: l, err: err}
}(url)
}
go func() {
wg.Wait()
close(resChan)
}()
for r := range resChan {
if r.err != nil {
log.Printf("failed to fetch %q: %v\n", r.url, r.err)
continue
}
fmt.Printf("%s has length %d\n", r.url, r.len)
}
}
這并不理想,因?yàn)樗粫?huì)限制并發(fā)傳出請(qǐng)求的數(shù)量。
關(guān)于,2) How to profile the status of go-routines for a given process?
請(qǐng)參閱 pprof 工具。有一個(gè)文檔https://golang.org/doc/diagnostics.html
- 2 回答
- 0 關(guān)注
- 114 瀏覽
添加回答
舉報(bào)