Zum Hauptinhalt springen

Timeout - Context package

Timeout with the context-package

  • handling Timout in a fetch request, ex. some Http request on another external server, where we do not know when or if we will get a reply.
package main

import (
"context"
"fmt"
"log"
"time"
)

func main(){
timerStart := time.Now()
ctx := context.Background()
userId := 123
val, err := fetchUserData(ctx, userId)
if err != nil{
log.Fatal(err)
}
fmt.Println("Fetched Data: ", val)
fmt.Println("it took: ", time.Since(timerStart))
}

type Response struct{
value string
err error
}

func fetchUserData(ctx context.Context, userId int) (string, error){
timeOutLimit := time.Millisecond *600
ctx, cancel := context.WithTimeout(ctx, timeOutLimit)
defer cancel() //cancel the timeout-counter on success

responseChannel := make(chan Response)
go func(){
val, err := fetchSomethingSlow()
responseChannel <- Response{
value: val,
err: err,
}
}()

for {
select{
case <- ctx.Done():
return "", fmt.Errorf("Error: Timeout, fetching data took to long.")
case res := <- responseChannel:
return res.value, res.err
}
}
}

func fetchSomethingSlow() (string, error){
time.Sleep(time.Millisecond * 1500)
return "<http>Hello World!</http>", nil
}

Shared State with the context-package

  • store variables in context.
  • so we can create some data that all our go-methods can share, a bit like [state, setState] = useState()
func main(){
timerStart := time.Now()

key, value := "foo", "currentState"
ctx := context.WithValue(context.Background(), key, value)
userId := 123
val, err := fetchUserData(ctx, userId)
if err != nil{
log.Fatal(err)
}
fmt.Println("Fetched Data: ", val)
fmt.Println("it took: ", time.Since(timerStart))
}

func fetchUserData(ctx context.Context, userId int) (string, error){
state := ctx.Value("foo")
fmt.Println(state)
timeOutLimit := time.Millisecond *600
ctx, cancel := context.WithTimeout(ctx, timeOutLimit)
defer cancel() //cancel the timeout-counter on success

responseChannel := make(chan Response)
go func(){
val, err := fetchSomethingSlow()
responseChannel <- Response{
value: val,
err: err,
}
}()

for {
select{
case <- ctx.Done():
return "", fmt.Errorf("Error: Timeout, fetching data took to long.")
case res := <- responseChannel:
return res.value, res.err
}
}
}