İstemci uygulamanız bir sunucu uygulamasını çağırıyorsa, yanıtın mümkün olduğunca hızlı geri gelmesini istersiniz. Ancak, işlem yavaşsa işlemi iptal edebilirsiniz. Bu gibi durumlar için context WithTimeout veya WithCancel özelliğini kullanabilirsiniz.


Uygulama


package main

import (
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)

func main() {
handler := http.NewServeMux()
handler.HandleFunc("/client/api/v1/users", controller)

log.Fatal(http.ListenAndServe(":8080", handler))
}

func controller(w http.ResponseWriter, _ *http.Request) {
res, err := users()
if err != nil {
_, _ = w.Write([]byte(err.Error()))
return
}

body, err := ioutil.ReadAll(res.Body)
if err != nil {
_, _ = w.Write([]byte(err.Error()))
return
}
res.Body.Close()

_, _ = w.Write(body)
}

// See users() function below for examples.

İstemci yolu


Her ne kadar bu yazı context hakkında olsada, tüm iptal işlemini aşağıda gösterildiği gibi http.Client.Timeout parametresini kullanarakta yapabilirsiniz.


func users() (*http.Response, error) {
req, err := http.NewRequest(http.MethodGet, "http://localhost:8090/server/api/v1/users", nil)
if err != nil {
return nil, err
}

client := http.Client{Timeout: 1 * time.Second}
res, err := client.Do(req)
if err != nil {
fmt.Printf("%t\n", err)
fmt.Printf("%T\n", err)

return nil, err
}

return res, nil
}

Test


İstemci zaman aşımı oluşursa hata bir * url.Error örneği olur ve içerik aşağıdakine benzer.


&{
%!t(string=Get)
%!t(string=http://localhost:8090/server/api/v1/users)
%!t(*http.httpError=&{
net/http: request canceled (Client.Timeout exceeded while awaiting headers)
true
}
)
}

WithTimeout


func users() (*http.Response, error) {
req, err := http.NewRequest(http.MethodGet, "http://localhost:8090/server/api/v1/users", nil)
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
defer cancel()

client := http.Client{}
res, err := client.Do(req.WithContext(ctx))
if err != nil {
fmt.Printf("%t\n", err)
fmt.Printf("%T\n", err)

return nil, err
}

return res, nil
}

Test


İstemci isteğinin contexinde zaman aşımı oluşursa hata bir *url.Error örneği olur ve içerik aşağıdakine benzer.


&{
%!t(string=Get)
%!t(string=http://localhost:8090/server/api/v1/users)
{}
}

WithCancel


func users() (*http.Response, error) {
req, err := http.NewRequest(http.MethodGet, "http://localhost:8090/server/api/v1/users", nil)
if err != nil {
return nil, err
}

ctx, cancel := context.WithCancel(context.Background())
_ = time.AfterFunc(1 * time.Second, func() { cancel() })

client := http.Client{}
res, err := client.Do(req.WithContext(ctx))
if err != nil {
fmt.Printf("%t\n", err)
fmt.Printf("%T\n", err)

return nil, err
}

return res, nil
}

Test


İstemci isteğinin contexinde iptal işlemi oluşursa hata bir *url.Error örneği olur ve içerik aşağıdakine benzer.


&{
%!t(string=Get)
%!t(string=http://localhost:8090/server/api/v1/users)
%!t(*errors.errorString=&{
context canceled
}
)
}