第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

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

帶上下文取消的異步/等待模式

帶上下文取消的異步/等待模式

Go
qq_笑_17 2022-06-13 15:28:25
在我的應(yīng)用程序中,我需要具有上下文取消支持的異步/等待模式。在實踐中,我有一個類似的功能:func longRunningTask() <-chan int32 {    r := make(chan int32)    go func() {        defer close(r)                // Simulate a workload.        time.Sleep(time.Second * 3)        r <- rand.Int31n(100)    }()    return r}但是,它不支持上下文取消。為了解決這個問題,我可以添加一個參數(shù)并修改函數(shù)以ctx.Done()在 select 語句中等待通道信號,如果上下文被取消則中止操作。如果這樣做,如果運行兩次或更多次,函數(shù)將不會正確中止(因為上下文指針將被共享),因為上下文取消通道只接收一個信號:ctx := ...go func() { r := <-longRunningTask(ctx) } // Done() worksgo func() { r := <-longRunningTask(ctx) } // ?// cancel() ...這是我看到的關(guān)于完成的內(nèi)容:   // go/context.go   357  func (c *cancelCtx) Done() <-chan struct{} {   358      c.mu.Lock()   359      if c.done == nil {   360          c.done = make(chan struct{})   361      }   362      d := c.done   363      c.mu.Unlock()   364      return d   365  } // Done() returns the same channel for all callers, and cancellation signal is sent once onlygo 源是否context真的不支持中止調(diào)用其他“長時間運行”函數(shù)的函數(shù),“鏈?zhǔn)饺∠??有哪些選項可以編寫支持在無限遞歸.Done()使用中取消上下文的異步函數(shù)?
查看完整描述

1 回答

?
有只小跳蛙

TA貢獻1824條經(jīng)驗 獲得超8個贊

go 源是否意味著上下文并不真正支持調(diào)用其他“長時間運行”函數(shù)的函數(shù)的中止,“鏈?zhǔn)饺∠保?/p>

不可以。任務(wù)可以調(diào)用其他長時間運行的任務(wù),將上下文傳遞到調(diào)用鏈中。這是一種標(biāo)準(zhǔn)做法。如果上下文被取消,嵌套調(diào)用將出錯并沿著調(diào)用堆棧冒泡取消錯誤


有哪些選項可以編寫異步函數(shù),以支持在 .Done() 使用的無限遞歸中取消上下文?

遞歸與幾個采用上下文的嵌套調(diào)用沒有什么不同。如果遞歸調(diào)用采用上下文輸入?yún)?shù)并返回錯誤(即檢查),則遞歸調(diào)用鏈將像一組非遞歸嵌套調(diào)用一樣冒泡取消事件。


首先,讓我們更新您的包裝函數(shù)以支持context.Context:


func longRunningTask(ctx context.Context) <-chan int32 {

    r := make(chan int32)


    go func() {

        defer close(r)

        

        // workload

        i, err := someWork(ctx)

        if err != nil {

            return

        }

        r <- i

    }()


    return r

}

然后someWork- 使用睡眠工作負載將如下所示:


func someWork(ctx context.Context) (int32, error) {


    tC := time.After(3*time.Second) // fake workload


    // we can check this "workload" *AND* the context at the same time

    select {

    case <-tC:

        return rand.Int31n(100), nil

    case <-ctx.Done():

        return 0, ctx.Err()

    }

}

這里要注意的重要一點是,我們可以改變虛假的“工作負載”(time.Sleep),使其成為一個通道——從而通過select語句觀察它和我們的上下文。大多數(shù)工作負載當(dāng)然不是那么簡單……


幸運的是,Go 標(biāo)準(zhǔn)庫完全支持context.Context. 因此,如果您的工作負載包含大量可能長時間運行的 SQL 查詢,則可以為每個查詢傳遞一個上下文。與 HTTP 請求或 gRPC 調(diào)用相同。如果您的工作負載包含這些調(diào)用中的任何一個,則傳入父上下文將導(dǎo)致任何這些潛在的阻塞調(diào)用在上下文被取消時返回錯誤 - 因此您的工作負載將返回取消錯誤,讓調(diào)用者知道什么發(fā)生了。


如果您的工作負載不適合此模型,例如計算大型 Mandelbrot-Set 圖像。在每個像素后檢查取消上下文可能會對性能產(chǎn)生負面影響,因為輪詢選擇不是免費的:


select {

case <-ctx.Done(): // polling select when `default` is included

    return ctx.Err()

default:

}

在這種情況下,可以應(yīng)用調(diào)整,如果說像素以 10,000/s 的速率計算 - 每 10,000 個像素輪詢上下文將確保任務(wù)將在取消點后不遲于 1 秒內(nèi)返回。


查看完整回答
反對 回復(fù) 2022-06-13
  • 1 回答
  • 0 關(guān)注
  • 141 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號