中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

網站開發(fā)文檔包括長春網站建設方案咨詢

網站開發(fā)文檔包括,長春網站建設方案咨詢,上海閔行建網站公司,順德公司網站制作目錄 基于現有的 context 創(chuàng)建新的 context 現有創(chuàng)建方法的問題 Go 1.21 中的 context.WithoutCancel 函數 Go 版本低于 1.21 該怎么辦? 在 Golang 中,context 包提供了創(chuàng)建和管理上下文的功能。當需要基于現有的 context.Context 創(chuàng)建新的 context …

目錄

基于現有的 context 創(chuàng)建新的 context

現有創(chuàng)建方法的問題

Go 1.21 中的 context.WithoutCancel 函數

Go 版本低于 1.21 該怎么辦?


在 Golang 中,context 包提供了創(chuàng)建和管理上下文的功能。當需要基于現有的 context.Context 創(chuàng)建新的 context 時,通常是為了添加額外的控制信息或為了滿足特定的生命周期需求。

基于現有的 context 創(chuàng)建新的 context

可以基于現有的 context.Context 創(chuàng)建一個新的 context,對應的函數有 context.WithCancel、context.WithDeadline、context.WithTimeout 或 context.WithValue。這些函數會返回一個新的 context.Context 實例,繼承了原來 context 的行為,并添加了新的行為或值。使用 context.WithValue 函數創(chuàng)建的簡單示例代碼如下:

package mainimport "context"func main() {// 假設已經有了一個context ctxctx := context.Background()// 可以通過context.WithValue創(chuàng)建一個新的contextkey := "myKey"value := "myValue"newCtx := context.WithValue(ctx, key, value)// 現在newCtx包含了原始ctx的所有數據,加上新添加的鍵值對
}

使用 context.WithCancel 函數創(chuàng)建,簡單示例代碼如下:

package mainimport "context"func main() {// 假設已經有了一個context ctxctx := context.Background()// 創(chuàng)建一個可取消的contextnewCtx, cancel := context.WithCancel(ctx)// 當完成了newCtx的使用,可以調用cancel來取消它// 這將釋放與該context相關的資源defer cancel()
}

現有創(chuàng)建方法的問題

先說一個使用場景:一個接口處理完基本的任務之后,后續(xù)一些處理的任務放使用新開的 Goroutine 來處理,這時候會基于當前的 context 創(chuàng)建一個 context(可以使用上面提到的方法來創(chuàng)建) 給 Goroutine 使用,也不需要控制 Goroutine 的超時時間。

這種場景下,Goroutine 的聲明周期一般都會比這個接口的生命周期長,這就會出現一個問題——當前接口請求所屬的?Goroutine 退出后會導致 context 被 cancel,進而導致新開的 Goroutine 中的 context 跟著被 cancel, 從而導致程序異常??匆粋€示例:

package mainimport ("bytes""context""errors""fmt""io""net/http""github.com/gin-gonic/gin"
)func main() {r := gin.New()r.GET("/test", func(c *gin.Context) {// 父 context,有使用取消功能ctx, cancel := context.WithCancel(c)defer cancel()// 創(chuàng)建子 context 給新開的 Goroutine 使用ctxCopy, _ := context.WithCancel(ctx)go func() {err := TestPost(ctxCopy)fmt.Println(err)}()})r.Run(":8080")
}func TestPost(ctx context.Context) error {fmt.Println("goroutine...")buffer := bytes.NewBuffer([]byte(`{"xxx":"xxx"}`))request, err := http.NewRequest("POST", "http://xxx.luduoxin.com/xxx", buffer)if err != nil {return err}request.Header.Set("Content-Type", "application/json")client := http.Client{}rsp, err := client.Do(request.WithContext(ctx))if err != nil {return err}defer func() {_ = rsp.Body.Close()}()if rsp.StatusCode != http.StatusOK {return errors.New("response exception")}_, err = io.ReadAll(rsp.Body)if err != nil {return err}return nil
}

運行代碼,在瀏覽器中訪問?http://127.0.0.1:8080/test,控制臺會打印如下錯誤信息:

goroutine...
Post "http://xxx.luduoxin.com/xxx": context canceled

可以看出,因為父級 context 被 cancel,導致子 context 也被 cancel,從而導致程序異常。因此,需要一種既能繼承父 context 所有的 value 信息,又能去除父級 context 的 cancel 機制的創(chuàng)建函數。

Go 1.21 中的 context.WithoutCancel 函數

這種函數該如何實現呢?其實 Golang 從 1.21 版本開始為我們提供了這樣一個函數,就是 context 包中的?WithoutCancel 函數。源代碼如下:

func WithoutCancel(parent Context) Context {if parent == nil {panic("cannot create context from nil parent")}return withoutCancelCtx{parent}
}type withoutCancelCtx struct {c Context
}func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {return
}func (withoutCancelCtx) Done() <-chan struct{} {return nil
}func (withoutCancelCtx) Err() error {return nil
}func (c withoutCancelCtx) Value(key any) any {return value(c, key)
}func (c withoutCancelCtx) String() string {return contextName(c.c) + ".WithoutCancel"
}

原理其實很簡單,主要功能是創(chuàng)建一個新的 context 類型,繼承了父 context 的所有屬性,但重寫了 Deadline、Done、Err、Value 幾個方法,當父 context 被取消時不會觸發(fā)任何操作。

Go 版本低于 1.21 該怎么辦?

如果 Go 版本低于 1.21 其實也很好辦,按照 Go 1.21 中的實現方式自己實現一個就可以了,代碼可以進一步精簡,示例代碼如下:

func WithoutCancel(parent Context) Context {if parent == nil {panic("cannot create context from nil parent")}return withoutCancelCtx{parent}
}type withoutCancelCtx struct {context.Context
}func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {return
}func (withoutCancelCtx) Done() <-chan struct{} {return nil
}func (withoutCancelCtx) Err() error {return nil
}

使用自己實現的這個版本再跑一下之前的示例,代碼如下:

package mainimport ("bytes""context""errors""fmt""io""net/http""time""github.com/gin-gonic/gin"
)func main() {r := gin.New()r.GET("/test", func(c *gin.Context) {// 父 context,有使用取消功能ctx, cancel := context.WithCancel(c)defer cancel()// 創(chuàng)建子 context 給新開的 Goroutine 使用ctxCopy := WithoutCancel(ctx)go func() {err := TestPost(ctxCopy)fmt.Println(err)}()})r.Run(":8080")
}func WithoutCancel(parent Context) Context {if parent == nil {panic("cannot create context from nil parent")}return withoutCancelCtx{parent}
}type withoutCancelCtx struct {context.Context
}func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {return
}func (withoutCancelCtx) Done() <-chan struct{} {return nil
}func (withoutCancelCtx) Err() error {return nil
}func TestPost(ctx context.Context) error {fmt.Println("goroutine...")buffer := bytes.NewBuffer([]byte(`{"xxx":"xxx"}`))request, err := http.NewRequest("POST", "http://xxx.luduoxin.com/xxx", buffer)if err != nil {return err}request.Header.Set("Content-Type", "application/json")client := http.Client{}rsp, err := client.Do(request.WithContext(ctx))if err != nil {return err}defer func() {_ = rsp.Body.Close()}()if rsp.StatusCode != http.StatusOK {return errors.New("response exception")}_, err = io.ReadAll(rsp.Body)if err != nil {return err}return nil
}type Context interface {Deadline() (deadline time.Time, ok bool)Done() <-chan struct{}Err() errorValue(key any) any
}

運行代碼,在瀏覽器中訪問 http://127.0.0.1:8080/test,發(fā)現不再報父 context 被 cancel 導致的報錯了。

http://www.risenshineclean.com/news/5520.html

相關文章:

  • 江蘇省建設廳網站施工員證查詢營銷比較好的知名公司有哪些
  • 免費php網站源碼信息流推廣渠道有哪些
  • 網站建設中 模版模板建站哪里有
  • 網站做任務賺錢優(yōu)化設計六年級下冊語文答案
  • 淄博團購網站建設紋身網站設計
  • 旅游酒店網站建設公司網站建設多少錢
  • 本地建設網站寧波網站制作優(yōu)化服務
  • 怎么用ps切片在dw里做網站百度收錄時間
  • 家具網站模板百度客戶電話
  • 做服裝加工哪個網站比較好溫州seo推廣外包
  • 黑龍江進入疫情緊急狀態(tài)seo需要什么技術
  • 外包公司做的網站怎么改密碼站長之家app下載
  • 1688網站上自己做模版專業(yè)營銷團隊公司
  • 阿里云網站如何建設視頻新浪微博指數查詢
  • 快速 模板 做網站百度網址安全檢測
  • 焦作市住房和城鄉(xiāng)建設局網站百度競價推廣登陸
  • 潛江做網站太原做網站推廣的公司
  • 韶關網站建設網站排名seo
  • 用ps做網站網頁百度排名服務
  • 網站建設崗位工作范圍怎樣注冊網站建立網頁
  • 成都網站外包優(yōu)化公司可以免費發(fā)外鏈的論壇
  • 推進網站集約化建設的作用推廣普通話手抄報一等獎
  • 網絡優(yōu)化報告seo外包網絡公司
  • 做網站下載別人的圖算不算侵權北京網站sem、seo
  • 整站關鍵詞排名優(yōu)化員工培訓
  • 網站的空間的提供商南京網站制作設計
  • 畢業(yè)答辯ppt網站開發(fā)百度大數據分析平臺
  • 網頁設計師證書查詢官網google seo怎么優(yōu)化
  • 精美網頁設計源碼網站seo優(yōu)化外包顧問
  • 龍山建設集團有限公司網站云南優(yōu)化公司