最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Golang的Context管理上下文的方法

 更新時間:2019年09月05日 11:14:26   作者:mingkai_beijing  
這篇文章主要介紹了使用Golang的Context管理上下文的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

golang 1.7版本中context庫被很多標準庫的模塊所使用,比如net/http和os的一些模塊中,利用這些原生模塊,我們就不需要自己再寫上下文的管理器了,直接調用函數接口即可實現,利用context我們可以實現一些比如請求的聲明周期內的變量管理,執(zhí)行一些操作的超時等等。

保存上下文對象

這里我們通過一個簡單的例子來看一下如何使用context的特性來實現上下文的對象保存,這里我們寫了一個簡單的http server,具有登錄和退出,狀態(tài)檢查路由(檢查用戶是否登錄)

func main(){
  mux:=http.NewServeMux()
  mux.HandleFunc("/",StatusHandler)
  mux.HandleFunc("/login",LoginHandler)
  mux.HandleFunc("/logout",LogoutHandler)
  contextedMux:=AddContextSupport(mux)
  log.Fatal(http.ListenAndServe(":8080",contextedMux))
}

其中的AddContextSupport是一個中間件,用來綁定一個context到原來的handler中,所有的請求都必須先經過該中間件后才能進入各自的路由處理中。具體的實現代碼如下:

func AddContextSupport(next http.Handler)http.Handler{
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    log.Println(r.Method, "-", r.RequestURI)
    cookie, _ := r.Cookie("username")
    if cookie != nil {
      ctx := context.WithValue(r.Context(), "username", cookie.Value)
      // WithContext returns a shallow copy of r with its context changed
      // to ctx. The provided ctx must be non-nil.
      next.ServeHTTP(w, r.WithContext(ctx))
    } else {
      next.ServeHTTP(w, r)
    }
  })
}

該中間件可以打印每次請求的方法和請求的url,然后獲得請求的cookie值,如果cookie為空的話則繼續(xù)傳遞到對應的路由處理函數中,否則保存cookie的值到Context, 注意這里的Context()是request對象的方法, 將創(chuàng)建一個新的上下文對象(如果context為空),context.WithValue()函數將key和value保存在新的上下文對象中并返回該對象。

其余的路由處理函數代碼如下, 分別用來保存cookie的登錄路由LoginHandler(),還有刪除cookie的退出路由處理函數LogoutHandler()。

func LoginHandler(w http.ResponseWriter,r *http.Request){
  expitation := time.Now().Add(24*time.Hour)
  var username string
  if username=r.URL.Query().Get("username");username==""{
    username = "guest"
  }
  cookie:=http.Cookie{Name:"username",Value:username,Expires:expitation}
  http.SetCookie(w,&cookie)
}

func LogoutHandler(w http.ResponseWriter, r *http.Request) {
  expiration := time.Now().AddDate(0, 0, -1)
  cookie := http.Cookie{Name: "username", Value: "alice_cooper@gmail.com", Expires: expiration}
  http.SetCookie(w, &cookie)
}

這里我們在請求/login的時候,可以傳遞一個參數username到函數中,比如/login?username=alice , 默認為”guest”用戶. 設置的cookie有效期為1天,刪除的時候我們只需要設置cookie為之前的日期即可。

另外一個關鍵的部分是讀取上下文保存內容的 StatusHandler() 路由處理函數,該函數將調用r.Context()獲得request的上下文,如果我們執(zhí)行了login后,那我們在中間件中已經設置了該對象,所以請求將查看是否上下文對象中保存了一個名為username的對象,如果有的話則回應一個歡迎頁面。否則告知用戶沒有登錄。

func StatusHandler(w http.ResponseWriter,r *http.Request){

  if username:=r.Context().Value("username"); username!=nil{
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Hi username:"+username.(string)+"\n"))
  }else{
    w.WriteHeader(http.StatusNotFound)
    w.Write([]byte("Not Logged in"))
  }
}

我們不僅僅可以在上下文中保存簡單的類型,我們可以保存任何類型的數據,因為Value() 返回的對象是一個interface{}對象,所以我們需要轉換一下才能使用。

超時處理

對于簡單的保存和傳遞對象,使用context的確很方便,但是該庫的使用不僅僅是保存變量,還可以創(chuàng)建一個超時和取消的行為,比如說我們web端去請求了其他的資源,但是該資源的處理比較耗時,我們無法預見什么時候能夠返回,如果讓用戶超時的話,實在是不太好,所以我們需要創(chuàng)建一個超時的操作,主動判斷是否超時,然后傳遞一個合適的行為給用戶。

這里我們現在路由中增加一個長期運行的job路由

mux.HandleFunc("/longjob",jobWithCancelHandler)

具體的處理如下,我們的handler會利用WithCancel() 返回一個新的(如果沒有創(chuàng)建)或者原來已保存的上下文,還有一個cancel對象,這個對象可以用來手動執(zhí)行取消操作。另外我們的url中可以指定這個任務模擬執(zhí)行的長度,比如/longjob?jobtime=10則代表模擬的任務將會執(zhí)行超過10秒。 執(zhí)行任務的函數longRunningCalculation()返回一個chan該chan會在執(zhí)行時間到期后寫入一個Done字符串。

handler中我們就可以使用select語句監(jiān)聽兩個非緩存的channel,阻塞直到有數據寫到任何一個channel中。比如代碼中我們設置了超時是5秒,而任務執(zhí)行10秒的話則5秒到期后ctx.Done()會因為cancel()的調用而寫入數據,這樣該handler就會因為超時退出。否則的話則執(zhí)行正常的job處理后獲得傳遞的“Done”退出。

func longRunningCalculation(timeCost int)chan string{

  result:=make(chan string)
  go func (){
    time.Sleep(time.Second*(time.Duration(timeCost)))
    result<-"Done"
  }()
  return result
}
func jobWithCancelHandler(w http.ResponseWriter, r * http.Request){
  var ctx context.Context
  var cancel context.CancelFunc
  var jobtime string
  if jobtime=r.URL.Query().Get("jobtime");jobtime==""{
    jobtime = "10"
  }
  timecost,err:=strconv.Atoi(jobtime)
  if err!=nil{
    timecost=10
  }
  log.Println("Job will cost : "+jobtime+"s")
  ctx,cancel = context.WithCancel(r.Context())
  defer cancel()

  go func(){
    time.Sleep(5*time.Second)
    cancel()
  }()

  select{
  case <-ctx.Done():
    log.Println(ctx.Err())
    return
  case result:=<-longRunningCalculation(timecost):
    io.WriteString(w,result)
  }
  return
}

這就是使用context的一些基本方式,其實context還有很多函數這里沒有涉及,比如WithTimeout和WithDeadline等,但是使用上都比較相似,這里就不在舉例。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Golang中interface{}轉為數組的操作

    Golang中interface{}轉為數組的操作

    這篇文章主要介紹了Golang中interface{}轉為數組的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • golang并發(fā)編程中Goroutine 協(xié)程的實現

    golang并發(fā)編程中Goroutine 協(xié)程的實現

    Go語言中的協(xié)程是一種輕量級線程,通過在函數前加go關鍵字來并發(fā)執(zhí)行,具有動態(tài)棧、快速啟動和低內存使用等特點,本文就來詳細的介紹一下,感興趣的可以了解一下
    2024-10-10
  • GoLang中socket心跳檢測的實現

    GoLang中socket心跳檢測的實現

    本文主要介紹了GoLang中socket心跳檢測的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-02-02
  • Go語言網站使用異步編程和Goroutine提高Web的性能

    Go語言網站使用異步編程和Goroutine提高Web的性能

    作為一門現代化編程語言,Go語言提供了強大的異步編程能力,使得程序員可以以更高效的方式處理并發(fā)任務,在Go語言中,使用Goroutine在單個進程中實現多任務并行處理,以及如何使用協(xié)程池來進一步提高Web服務器的處理能力,
    2024-01-01
  • Go設計模式之觀察者模式圖解

    Go設計模式之觀察者模式圖解

    觀察者模式是一種行為設計模式, 允許你定義一種訂閱機制, 可在對象事件發(fā)生時通知多個 “觀察” 該對象的其他對象,下面這篇文章主要給大家介紹了關于圖解Go觀察者模式的相關資料,需要的朋友可以參考下
    2023-07-07
  • Go語言中實現打印堆棧的errors包的用法詳解

    Go語言中實現打印堆棧的errors包的用法詳解

    因為Go語言提供的錯誤太簡單了,以至于簡單的我們無法更好的處理問題,所以誕生了很多對錯誤處理的庫,github.com/pkg/errors是比較簡潔的一樣,本文就來聊聊它的具體用法吧
    2023-07-07
  • Go中的新增對模糊測試的支持

    Go中的新增對模糊測試的支持

    這篇文章主要為大家介紹了Go中的新增對模糊測試的支持,文中還包含了一些功能實驗性測試分析有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • Go切片的具體使用

    Go切片的具體使用

    本文主要介紹了Go切片的具體使用,包括聲明切片、初始化切片、切片的切割、切片的添加、切片的刪除、切片的復制、切片的遍歷、多維切片等,感興趣的可以了解一下
    2023-11-11
  • 用go gin server來做文件上傳服務

    用go gin server來做文件上傳服務

    今天小編就為大家分享一篇關于用go gin server來做文件上傳服務,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Golang泛型的使用方法詳解

    Golang泛型的使用方法詳解

    這篇文章主要介紹了Golang中泛型的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06

最新評論

若尔盖县| 博罗县| 宿松县| 叙永县| 南汇区| 贵南县| 四平市| 老河口市| 武清区| 临汾市| 保定市| 南靖县| 襄城县| 永定县| 芜湖县| 房产| 正安县| 东海县| 嘉祥县| 城市| 南江县| 怀宁县| 桐梓县| 涞水县| 金坛市| 博罗县| 清新县| 正镶白旗| 岳池县| 沁水县| 汝南县| 崇文区| 抚顺市| 泰顺县| 长丰县| 克什克腾旗| 鄂尔多斯市| 习水县| 长宁县| 琼结县| 西安市|