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

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

如果上下文被取消,則終止函數(shù)執(zhí)行

如果上下文被取消,則終止函數(shù)執(zhí)行

Go
qq_遁去的一_1 2022-06-06 15:33:23
我有這個最初不支持上下文的當前函數(shù)。func (s *Service) ChunkUpload(r *multipart.Reader) error {    chunk, err := s.parseChunk(r)    if err != nil {        return fmt.Errorf("failed parsing chunk %w", err)    }    if err := os.MkdirAll(chunk.UploadDir, 02750); err != nil {        return err    }    if err := s.saveChunk(chunk); err != nil {        return fmt.Errorf("failed saving chunk %w", err)    }    return nil}我已經(jīng)更新了它的方法調(diào)用,現(xiàn)在將 acontext.Context作為它的第一個參數(shù)。我的主要目標是在上下文被取消后立即終止并返回函數(shù)。我最初的實現(xiàn)是這樣的。func (s *Service) ChunkUpload(ctx context.Context, r *multipart.Reader) error {    errCh := make(chan error)    go func() {        chunk, err := s.parseChunk(r)        if err != nil {            errCh <- fmt.Errorf("failed parsing chunk %w", err)            return        }        if err := os.MkdirAll(chunk.UploadDir, 02750); err != nil {            errCh <- err            return        }        if err := s.saveChunk(chunk); err != nil {            errCh <- fmt.Errorf("failed saving chunk %w", err)            return        }    }()    select {    case err := <-errCh:        return err    case <-ctx.Done():        return ctx.Err()    }}然而,當我想到代碼的執(zhí)行時,我意識到這并沒有達到我的目標。由于所有函數(shù)的邏輯都在一個單獨的 go 例程中,即使上下文被取消并且我ChunkUpload提前返回,go 例程中的代碼將繼續(xù)執(zhí)行,因此與原始代碼沒有真正的區(qū)別。下一個雖然可以,只需將上下文傳遞給所有內(nèi)部函數(shù),例如s.parseChunk,s.saveChunk但是這個選項似乎也不正確,因為我需要在每個函數(shù)中實現(xiàn)取消。將這個原始函數(shù)重構(gòu)為上下文感知并在上下文被取消后立即終止的正確方法是什么?
查看完整描述

2 回答

?
斯蒂芬大帝

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

函數(shù)調(diào)用和 goroutines 不能被調(diào)用者終止,函數(shù)和 goroutines 必須支持取消,通常通過context.Context值或done通道。


在任何一種情況下,函數(shù)都負責檢查/監(jiān)視上下文,如果請求取消(當上下文的完成通道關(guān)閉時),則提前返回。沒有更簡單/自動的方法。


如果任務在循環(huán)中執(zhí)行代碼,一個方便的解決方案是在每次迭代中檢查完成的通道,如果它關(guān)閉則返回。如果任務是一個“整體”,則實現(xiàn)者負責使用/插入“檢查點”,如果請求取消,則可以合理地提前中止任務。


檢查 done 通道是否關(guān)閉的一種簡單方法是使用 non-blocking select,例如:


select {

case <-ctx.Done():

    // Abort / return early

    return

default:

}

當任務使用其他通道操作時必須小心,因為它們可能會以不確定的方式阻塞。這些選擇也應該包括ctx.Done()頻道:


select {

case v := <- someChannel:

    // Do something with v

case <-ctx.Done():

    // Abort / return early

    return

}

還要小心,因為如果上面的 receive from someChannelnever 阻塞,則不能保證正確處理取消,因為如果多個通信可以在 a 中進行select,則隨機選擇一個(并且不能保證<-ctx.Done()永遠選擇)。在這種情況下,您可以結(jié)合上述 2:首先對取消進行非阻塞檢查,然后將 aselect與您的通道操作和取消監(jiān)控一起使用。


查看完整回答
反對 回復 2022-06-06
?
溫溫醬

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

當我們談到取消時,我們談到了一個長期運行的函數(shù)或一個重復多次的塊,例如http.Serve()


至于您的情況,假設(shè)saveChunk運行將花費幾秒鐘,并且您想在保存時取消。所以我們可以把塊分成幾塊,在每一塊之后一個接一個地保存。


for i:=0;i<n;i++{

    select {

        case err := <- s.saveChunk(chunk[i]):

        {

             if err != nil {

                  fmt.Errorf("failed saving chunk %w", err)

                  return

              }

        }

        case <-ctx.Done():

              return

    }

}


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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