Go語言超時退出的三種實現方式總結
更新時間:2023年06月18日 09:38:35 作者:242030
這篇文章主要為大家詳細介紹了Go語言中超時退出的三種實現方式,文中的示例代碼簡潔易懂,對我們深入了解Go語言有一定的幫助,需要的可以了解一下
1、Go語言三種方式實現超時退出
1.1 context.WithTimeout/context.WithDeadline + time.After
// time.After(time.Duration(time.Millisecond * 700)) package main import ( "context" "fmt" "time" ) // Golang三種方式實現超時退出-方法1 // 場景:設定一個超時時間,若是在指定超時時間后沒有返回結果,則重試 func main() { // 經過context的WithTimeout設置一個有效時間為800毫秒的context // 該context會在耗盡800毫秒后或者方法執(zhí)行完成后結束,結束的時候會向通道ctx.Done發(fā)送信號 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800)) // 注意,這里要記得調用cancel(),否則即便提早執(zhí)行完了,還要傻傻等到800毫秒后context才會被釋放 defer cancel() go func(ctx context.Context) { // 發(fā)送HTTP請求 fmt.Println("處理請求!") time.Sleep(800 * time.Millisecond) fmt.Println("請求處理完畢!") }(ctx) select { case <-ctx.Done(): fmt.Println("call successfully!!!") return // 這里已經設置了context的有效時間,為何還要加上這個time.After呢 // 這是由于該方法內的context是本身聲明的,能夠手動設置對應的超時時間,可是在大多數場景,這里的ctx是從上游一直傳遞過來的, // 對于上游傳遞過來的context還剩多少時間,咱們是不知道的,因此這時候經過time.After設置一個本身預期的超時時間就頗有必要了 case <-time.After(time.Duration(time.Millisecond * 700)): fmt.Println("timeout!!!") return } }
程序輸出
處理請求!
timeout!!!
修改超時時間:
// time.After(time.Duration(time.Millisecond * 1000)) package main import ( "context" "fmt" "time" ) // Golang三種方式實現超時退出-方法1 // 場景:設定一個超時時間,若是在指定超時時間后沒有返回結果,則重試 func main() { // 經過context的WithTimeout設置一個有效時間為800毫秒的context // 該context會在耗盡800毫秒后或者方法執(zhí)行完成后結束,結束的時候會向通道ctx.Done發(fā)送信號 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800)) // 注意,這里要記得調用cancel(),否則即便提早執(zhí)行完了,還要傻傻等到800毫秒后context才會被釋放 defer cancel() go func(ctx context.Context) { // 發(fā)送HTTP請求 fmt.Println("處理請求!") time.Sleep(800 * time.Millisecond) fmt.Println("請求處理完畢!") }(ctx) select { case <-ctx.Done(): fmt.Println("call successfully!!!") return // 這里已經設置了context的有效時間,為何還要加上這個time.After呢 // 這是由于該方法內的context是本身申明的,能夠手動設置對應的超時時間,可是在大多數場景,這里的ctx是從上游一直傳遞過來的, // 對于上游傳遞過來的context還剩多少時間,咱們是不知道的,因此這時候經過time.After設置一個本身預期的超時時間就頗有必要了 case <-time.After(time.Duration(time.Millisecond * 1000)): fmt.Println("timeout!!!") return } }
程序輸出
處理請求!
請求處理完畢!
call successfully!!!
1.2 context.WithTimeout/context.WithDeadline + time.NewTimer
// time.NewTimer(time.Duration(time.Millisecond * 700)) package main import ( "context" "fmt" "time" ) // Golang三種方式實現超時退出-方法2 // 使用time.NewTimer func main() { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800)) defer cancel() timer := time.NewTimer(time.Duration(time.Millisecond * 700)) go func(ctx context.Context) { // 發(fā)送HTTP請求 fmt.Println("處理請求!") time.Sleep(800 * time.Millisecond) fmt.Println("請求處理完畢!") }(ctx) select { case <-ctx.Done(): timer.Stop() timer.Reset(time.Second) fmt.Println("call successfully!!!") return case <-timer.C: fmt.Println("timeout!!!") return } }
程序輸出
處理請求!
timeout!!!
修改超時間:
// time.NewTimer(time.Duration(time.Millisecond * 1000)) package main import ( "context" "fmt" "time" ) // Golang三種方式實現超時退出-方法2 // 使用time.NewTimer func main() { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800)) defer cancel() timer := time.NewTimer(time.Duration(time.Millisecond * 1000)) go func(ctx context.Context) { // 發(fā)送HTTP請求 fmt.Println("處理請求!") time.Sleep(800 * time.Millisecond) fmt.Println("請求處理完畢!") }(ctx) select { case <-ctx.Done(): timer.Stop() timer.Reset(time.Second) fmt.Println("call successfully!!!") return case <-timer.C: fmt.Println("timeout!!!") return } }
程序輸出
處理請求!
請求處理完畢!
call successfully!!!
1.3 channel + time.After/time.NewTimer
// time.After(time.Duration(700 * time.Millisecond)) package main import ( "context" "fmt" "time" ) // Golang三種方式實現超時退出-方法3 // 使用通道 func main() { ctx := context.Background() done := make(chan struct{}, 1) go func(ctx context.Context) { // 發(fā)送HTTP請求 fmt.Println("處理請求!") time.Sleep(800 * time.Millisecond) fmt.Println("請求處理完畢!") done <- struct{}{} }(ctx) select { case <-done: fmt.Println("call successfully!!!") return case <-time.After(time.Duration(700 * time.Millisecond)): fmt.Println("timeout!!!") return } }
程序輸出
處理請求!
timeout!!!
修改超時時間:
// time.After(time.Duration(1000 * time.Millisecond)) package main import ( "context" "fmt" "time" ) // Golang三種方式實現超時退出-方法3 // 使用通道 func main() { ctx := context.Background() done := make(chan struct{}, 1) go func(ctx context.Context) { // 發(fā)送HTTP請求 fmt.Println("處理請求!") time.Sleep(800 * time.Millisecond) fmt.Println("請求處理完畢!") done <- struct{}{} }(ctx) select { case <-done: fmt.Println("call successfully!!!") return case <-time.After(time.Duration(1000 * time.Millisecond)): fmt.Println("timeout!!!") return } }
程序輸出
處理請求!
請求處理完畢!
call successfully!!!
到此這篇關于Go語言超時退出的三種實現方式總結的文章就介紹到這了,更多相關Go語言超時退出內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Go語言中strings.HasPrefix、strings.Split、strings.SplitN()?函數
本文主要介紹了Go語言中strings.HasPrefix、strings.Split、strings.SplitN()函數,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-08-08Go語言入門教程之Arrays、Slices、Maps、Range操作簡明總結
這篇文章主要介紹了Go語言入門教程之Arrays、Slices、Maps、Range操作簡明總結,本文直接給出操作代碼,同時對代碼加上了詳細注釋,需要的朋友可以參考下2014-11-11