英文:
Context Timeout in GoLang
问题
使用Go API中的context.WithTimeout(context, time)实现了上下文超时。
期望的结果是,如果我将超时设置为10秒,并且如果API运行时间超过10秒,它应该停止并返回超时错误。然而,如果我在其中添加了一个sleep,API仍然会继续运行并返回200输出。除了在随机点手动检查经过的时间之外,是否有其他解决方案?看起来context.WithTimeout()没有实现其目的。
英文:
Implemented a context timeout in Go APIs using
context.WithTimeout(context,time)
Expectation is that if I set it to 10 seconds and if the API happens to run longer, it should stop and return Timeout error. However, if I add a sleep in between , the API still runs and gives 200 output. Is there any solution to this other than manually checking at random points for the time elapsed ? Looks like context.WithTimeout() doesnt solve its purpose.
答案1
得分: 1
所以,这是一个最小的代码示例,说明了如何使用context.WithTimeout函数:
server.go
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/bad", badResponse)
http.HandleFunc("/nice", niceResponse)
http.ListenAndServe(":8099", nil)
}
// badResponse是一个执行时间过长的过程
func badResponse(w http.ResponseWriter, r *http.Request) {
fmt.Println("收到请求,可能需要很长时间才能回复")
time.Sleep(3 * time.Second)
fmt.Fprintf(w, "糟糕的响应!")
}
// niceResponse是一个及时响应的过程
func niceResponse(w http.ResponseWriter, r *http.Request) {
fmt.Println("收到请求,将快速返回")
fmt.Fprintf(w, "好的响应!")
}
client.go
package main
import (
"context"
"io/ioutil"
"log"
"net/http"
"time"
)
func main () {
req, err := http.NewRequest(http.MethodGet, "http://localhost:8099/bad", nil)
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()
req = req.WithContext(ctx)
c := &http.Client{}
res, err := c.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
out, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatal(err)
}
log.Println(string(out))
}
在上面的示例中,客户端必须失败,因为超时时间小于服务器延迟时间。
英文:
So, this is a minimum code to exemplify how the context.WithTimeout can work:
server.go
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/bad", badResponse)
http.HandleFunc("/nice", niceResponse)
http.ListenAndServe(":8099", nil)
}
// badResponse is a procedure that takes too much time
func badResponse(w http.ResponseWriter, r *http.Request) {
fmt.Println("got request, it may take too long to answer")
time.Sleep(3 * time.Second)
fmt.Fprintf(w, "bad response!")
}
// niceResponse is a procedure that respond in time
func niceResponse(w http.ResponseWriter, r *http.Request) {
fmt.Println("got request, will return fast")
fmt.Fprintf(w, "nice response!")
}
client.go
package main
import (
"context"
"io/ioutil"
"log"
"net/http"
"time"
)
func main () {
req, err := http.NewRequest(http.MethodGet, "http://localhost:8099/bad", nil)
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()
req = req.WithContext(ctx)
c := &http.Client{}
res, err := c.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
out, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatal(err)
}
log.Println(string(out))
}
In the example above the client must fail because the timeout is lower than the client server delay.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论