Link to the original text :https://www.zhoubotong.site/post/57.html
golang Timeout processing for
As we all know Select yes Go A control structure in , Every case It has to be a communication operation , Either send or receive . select yes Randomly execute a runnable case.
without case Can run , The program may block , Until there is case Can run . Of course, there is a default clause (default Clause ) It can always run when no conditions are met .
For processing resource intensive applications , Overtime processing is inevitable . It is necessary to check the timeout , To ensure that tasks that run overtime do not consume resources or network bandwidth that other service components of the application may need .
Golang The method of dealing with timeout is very simple . No need for complex code , We can use channel Communication and use select Statement to make a timeout decision to deal with the timeout problem .
stay Go in ,Select Mainly and channel of , The approximate format is as follows :
select{
case <- ch1: // Read ch1
// Perform the operation
case i := <- ch2 // Read ch2
// Use i Perform the operation
default:
//
}
Go Of select And channel Use together for timeout processing .channel Must be buffered channel, Otherwise, it is synchronous operation .
select Used to wait for one or more channel Output .
Application scenarios
Lord goroutine Waiting for son goroutine complete , But son goroutine Unlimited operation , Cause the Lord goroutine Will wait forever ( Be careful main Also a Ctrip ). And the main thread wants to exceed a certain time, if it does not return ,
At this time, you can judge the timeout and continue to run .
package main import (
"fmt"
"time"
) func main() {
chn := make(chan bool, 1)
// Execute a function concurrently , wait for 3s Back chn write in true
go func() {
time.Sleep(3 * time.Second)
chn <- true
}() /*
Here will wait chn or timeout Read the data
Because I haven't been to chn Write data
stay 3s Back chn Write data
So it's implemented timeout Of case
Using this technique, you can realize timeout operation
*/
select {
case chn1 := <-chn:
fmt.Println(chn1)
return
case <-time.After(4 * time.Second): // Timeout judgment ( Program execution 4s after , because 3s Inside chn It has been sent true, So the output true)
fmt.Println(" Overtime timeout")
// If you will time.After Change to 1*time.Second, The output of :
return
} }
Let me give another example that is often used in development , For example, simulate network connection , We start with a simulation get Read the response from the requested service .
As follows, I write a simple structure to receive the response content of the service ( This example does not consider the timeout problem , I will explain later and add ).
type Result struct {
UserID int `json:"user_id"`
ID int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
Here I write a quick way to get the response in the service directly , And return it to the client , The complete code is as follows :
package main import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
) type Result struct {
UserID int `json:"user_id"`
ID int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
} // send out http get Request to obtain the corresponding data
func GetHttpResult(URL string) (*Result, error) {
resp, err := http.Get(URL) if err != nil {
return nil, fmt.Errorf(err.Error())
} defer resp.Body.Close()
byteResp, err := ioutil.ReadAll(resp.Body) if err != nil {
return nil, fmt.Errorf(err.Error())
} structResp := &Result{}
err = json.Unmarshal(byteResp, structResp) // analysis json Data to Result The value pointed to by the structure if err != nil {
return nil, fmt.Errorf("error in unmarshalling Result")
} return structResp, nil
}
func main() { res, err := GetHttpResult("https://jsonplaceholder.typicode.com/todos/1") // Normally, the request returns in milliseconds if err != nil {
fmt.Printf("err %v", err)
} else {
fmt.Printf("res %v", res)
}
}
This is a very simple method . Just use Golang Native http Library to read http Information in the call , And store the response content in the structure , Handle errors in different steps . It's simple !
As a result, a virtual response message from the simulation service is output as follows ( No timeout ):
res &{0 1 delectus aut autem false}
Now let's see that the request is normal , Suppose the connection takes a long time to get a response from the server , that main The function will wait indefinitely .
In a real application , It's unacceptable , Because it will consume a lot of resources . To solve this problem , We are GetHttpResult Add a... To the function context Parameters .
func GetHttpResult(ctx context.Context) (*Result, error)
This context Can tell us when to stop trying to get results from the network . To test this , First write a help function , Perform the same operation as before , Return the result and write it to channel,
And use a separate goroutine To perform the actual work . For the sake of simplicity , You can wrap responses and errors in one CallResult In the structure , The complete code is as follows :
package main import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
) // Define the response structure
type Result struct {
UserID int `json:"user_id"`
ID int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
} type CallResult struct {
Resp *Result
Err error
} func helper(ctx context.Context) <-chan *CallResult { respChan := make(chan *CallResult, 1) go func() {
resp, err := http.Get("https://jsonplaceholder.typicode.com/todos/1")
time.Sleep(2000 * time.Millisecond) // Simulate timeout request Millisecond Express 1 Millisecond interval
// Like sleep 1 Hours 10 branch 5 second :time.Sleep(1*time.Hour + 10*time.Minute + 5*time.Second) if err != nil {
respChan <- &CallResult{nil, fmt.Errorf(err.Error())}
return
} defer resp.Body.Close()
byteResp, err := ioutil.ReadAll(resp.Body) if err != nil {
respChan <- &CallResult{nil, fmt.Errorf(err.Error())}
return
} structResp := &Result{}
err = json.Unmarshal(byteResp, structResp) if err != nil {
respChan <- &CallResult{nil, fmt.Errorf("error in unmarshalling Result")}
} respChan <- &CallResult{structResp, nil}
}() return respChan
} func GetHttpResult(ctx context.Context) (*Result, error) {
select {
case <-ctx.Done():
return nil, fmt.Errorf("context timeout, ran out of time")
case respChan := <-helper(ctx):
return respChan.Resp, respChan.Err }
} func main() { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) // exceed 1s The response is marked as timeout
defer cancel()
res, err := GetHttpResult(ctx) if err != nil {
fmt.Printf("err %v", err)
} else {
fmt.Printf("res %v", res)
} }
Run the above code to get the same response information as before ( Comment out time.Sleep) Normal output :
res &{0 1 delectus aut autem false}
In the code shown above , Created a cached respChan passageway . Then execute and GetHttpResult Function works the same , But with a CallResult Instead of returning responses and errors .
The end of the function returns resChan. And then on its own goroutine Perform network connection in , And write the result to channel. In this way, the code realizes non blocking .
You can see GetHttpResult The function is now simpler , Because it has to make a simple choice . Either read the response from the channel or exit after timeout .
The above timeout strategy is implemented through select Statement to complete . Here are Done Definition of function :
Done() <-chan struct{}
Done Return to one channel, When it comes to context Be cancelled ,channel Will shut down . When context Timeout in , It will write to the channel when it times out .
under these circumstances , The code returns an error response message indicating timeout .
the other one case yes ,helper Function can complete the response reading of the service before timeout , And write channel. under these circumstances , stay respChan Get the result from the variable and return it to the client .
above main Call in function GetHttpResult And introduce a 1 Second timeout context Parameters . Then reduce the timeout to 1 millisecond (
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
), because 1 Not enough milliseconds to complete the network call . Therefore, it will not occupy any resources too much , And as long as context Overtime , It returns an error to the client , Instead of waiting for a response .
golang More related articles on timeout handling tips
- golang chan Overtime
golang chan Overtime Posted on 2013-12-24 13:03 oathleo read (4227) Comment on (0) edit Collection package main import ( &q ...
- Golang fmt Package use tips
h1 { margin-top: 0.6cm; margin-bottom: 0.58cm; direction: ltr; color: #000000; line-height: 200%; te ...
- Golang The pit prevention tips of
Golang The pit prevention tips of author : Yin Zhengjie Copyright notice : Original works , Declined reprint ! Otherwise, the legal liability will be investigated . As a little white , I didn't get in touch with programming partners before , It's hard to avoid stepping into some pits , For example, when you first get started, you need to install the environment , Study Gol ...
- golang Techniques for realizing variable parameters
Go Tips for using default parameters Functional Options Pattern in Go golang There is no design of function default parameters in , So special techniques are needed to achieve . If we need to order a batch of computers , Among them, computer configuration c ...
- golang Network communication timeout setting
In network communication , In order to prevent long-term non response , Network connection timeout is often used . Setting of read-write timeout . This article introduces with examples golang Connection timeout and read-write timeout settings . 1. timeout 1.1 Connection timeout func DialTimeou ...
- [Golang]-6 timeout handler 、 Non blocking channel operation 、 Channel closing and traversal
Catalog timeout handler Non blocking channel operation The closing of the channel Channel traversal timeout handler Overtime For a connection to external resources , Or other programs that take time to execute . Thanks to access and select, stay Go Realize timeout operation in ...
- golang RPC Communication read-write timeout setting
golang RPC In communication , Sometimes I'm afraid of reading and writing hang live . Can I set the read-write timeout ? 1. Scheme 1 : Set the read-write timeout of the connection 1.1 client RPC Communication is based on the underlying network communication , Can be set by connection ...
- Golang os/exec Realization
os/exec Realized golang call shell Or other OS Methods of existing commands in . This article is mainly a summary after reading the internal implementation . If you want to run ls -rlt, The code is as follows : package main import ...
- UVA-11214 Guarding the Chessboard ( Iteratively deepen the search )
The main idea of the topic : Place the queen on a chess board , Make all the targets occupied , Find the minimum number of queens . Topic analysis : Iteratively deepen the search , Otherwise, it will be overtime . Tips : use vis[0][r].vis[1][c].vis[2][r+c].vis[c- ...
- hihoCoder-1087 Hamiltonian Cycle ( Memory search )
describe Given a directed graph containing n vertice (numbered from 1 to n) and m edges. Can you tell us h ...
Random recommendation
- [ The software is recommended ]Windows Folder multi label tool Clover
Clover yes Windows Explorer An extension of the resource manager , Add something like Google to it Chrome Browser's multi tab function , The latest version is :3.1.7 Clover hold Chrome There's something about tabs ...
- Combination Sum
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique c ...
- 《HelloGitHub monthly 》 The first 03 period
<HelloGithub> The first 03 period Interest is the best teacher , and <HelloGitHub> It's about finding your interests ! Because I'm familiar with python Language , So in the monthly python Most of the language projects , individual ...
- STL1-unordered_map
I'm going to sort out what I met in the last few days STL Function of , Actually, I didn't intend to learn , I think it's useful C It can be completely realized , Why remember so many complex functions , So what I have done before will be commonly used C The function makes one by itself lib library , It's also very convenient to use , but ...
- 【CSS3】 Animation
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 【Android Studio Install deployment series 】 23 、Android studio see Gradle Version number
Copyright notice : This paper is about HaiyuKing Original article , Reprint please indicate the source ! summary File——Project Structure single click Project You can see , Current project gradle The version number is 4.4. Reference material An ...
- JDK Source code to see ArrayList and Vector Some of the differences
Recently in to see JDK Source code , Record it from the perspective of source code ArrayList and Vector Some of the differences 1.new a. Do not specify length Vector Created by default 10 Array of elements public Vector() { this(10 ...
- Big data technology - MapReduce Of Combiner Introduce
This chapter briefly introduces Hadoop MapReduce Medium Combiner.Combiner It appears to aggregate data , Then why aggregate data ? Because we know Shuffle The process is consuming the network IO and disk I ...
- net4log Add custom variables
stay log4net.config in <parameter> <parameterName value="@czyid" /> <dbType value ...
- HP The server Turn on ILO
=============================================== 2018/11/4_ The first 1 Time modification ccb_warlock == ...