亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

第一次完成時如何安全地繞過其他 goroutine 的結果

第一次完成時如何安全地繞過其他 goroutine 的結果

Go
狐的傳說 2021-11-22 10:45:50
我想向幾臺服務器詢問數據(例如多個只讀副本)。在這項任務中最重要的是速度,因此應該提供第一個結果,而其他所有結果都可以忽略。我對繞過這些數據的慣用方式有疑問。當它退出時,有這個問題的一切都沒有問題(所有較慢的 goroutine 都沒有完成它們的工作,因為主進程存在)。但是當我們取消最后一行的注釋(使用 Sleep)時,我們可以看到其他 goroutines 也在做他們的工作?,F在我正在通過通道推送數據有沒有辦法不推送它們?處理此類問題的好方法是什么?package mainimport (    "fmt"    "log"    "math/rand"    "time")type Result inttype Conn struct {    Id int}func (c *Conn) DoQuery(params string) Result {    log.Println("Querying start", params, c.Id)    time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)    log.Println("Querying end", params, c.Id)    return Result(1000 + c.Id*c.Id)}func Query(conns []Conn, query string) Result {    ch := make(chan Result)    for _, conn := range conns {        go func(c Conn) {            ch <- c.DoQuery(query)        }(conn)    }    return <-ch}func main() {    conns := []Conn{Conn{1}, Conn{2}, Conn{3}, Conn{4}, Conn{5}}    result := Query(conns, "query!")    fmt.Println(result)    // time.Sleep(time.Minute)}
查看完整描述

1 回答

?
千萬里不及你

TA貢獻1784條經驗 獲得超9個贊

我的建議是,使CH緩沖通道,每個查詢一個空間:ch := make(chan Result, len(conns))。這樣每個查詢都可以運行完成,并且不會阻塞通道寫入。


Query可以讀取一次并返回第一個結果。當所有其他 goroutine 完成時,通道最終將被垃圾回收,一切都會消失。使用無緩沖通道,您可以創建許多永遠不會終止的 goroutine。


編輯:如果你想取消飛行中的請求,它會變得更加困難。某些操作和 API 提供取消功能,而其他操作和 API 則不提供。對于 http 請求,您可以Cancel在請求結構上使用字段。只需提供一個您可以關閉以取消的頻道:


func (c *Conn) DoQuery(params string, cancel chan struct{}) Result {

    //error handling omitted. It is important to handle errors properly. 

    req, _ := http.NewRequest(...)

    req.Cancel = cancel

    resp, _ := http.DefaultClient.Do(req)

    //On Cancellation, the request will return an error of some kind.

    return readData(resp)

}

func Query(conns []Conn, query string) Result {

    ch := make(chan Result)

    cancel := make(chan struct{})

    for _, conn := range conns {

        go func(c Conn) {

            ch <- c.DoQuery(query,cancel)

        }(conn)

    }


    first := <-ch

    close(cancel)

    return first

}

如果有一個您不關心的大型讀取請求,這可能會有所幫助,但它實際上可能會或可能不會取消遠程服務器上的請求。如果您的查詢不是 http,而是數據庫調用或其他什么,您將需要查看是否有類似的取消機制可以使用。


查看完整回答
反對 回復 2021-11-22
  • 1 回答
  • 0 關注
  • 215 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號