我有一个Get()功能:func Get(url string) *Response { res, err := http.Get(url) if err != nil { return &Response{} } // res.Body != nil when err == nil defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("ReadAll: %v", err) } reflect.TypeOf(body) return &Response{sync.Mutex(),string(body), res.StatusCode}}以及一个Read()函数:func Read(url string, timeout time.Duration) (res *Response) { done := make(chan bool) go func() { res = Get(url) done <- true }() select { // As soon as either case <-done: // done is sent on the channel or case <-time.After(timeout): // timeout res = &Response{"Gateway timeout\n", 504} } return}Response函数返回的类型定义为:type Response struct { Body string StatusCode int}这个读取函数利用了Get()函数,也实现了超时。的问题是,如果发生超时和可发生数据争Get()响应被写入res在相同的时间Read()。我有一个如何解决这个问题的计划。就是使用互斥锁。为此,我将向Response结构中添加一个字段:type Response struct { mu sync.Mutex Body string StatusCode int}以便Response可以锁定。但是,我不确定如何在代码的其他部分解决这个问题。对于 Get(),我的尝试如下所示:func Get(url string) *Response { res, err := http.Get(url) if err != nil { return &Response{} } // res.Body != nil when err == nil defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("ReadAll: %v", err) } reflect.TypeOf(body) return &Response{sync.Mutex(),string(body), res.StatusCode} // This line is changed.}对于Read():func Read(url string, timeout time.Duration) (res *Response) { done := make(chan bool) res = &Response{sync.Mutex()} // this line has been added go func() { res = Get(url) done <- true }() select { case <-done: case <-time.After(timeout): res.mu.Lock() res = &Response{sync.Mutex(), "Gateway timeout\n", 504} // And mutex was added here. } defer res.mu.Unlock() return}在这种情况下使用互斥锁的正确方法是什么?
2 回答
慕无忌1623718
TA贡献1744条经验 获得超4个赞
虽然您对 Volker 的指导的回答很好,但您可能需要考虑使用非默认值,http.Client
以便您可以Timeout
在发出请求的客户端上设置 a (这样您就不必担心自己处理超时了)。
慕工程0101907
TA贡献1887条经验 获得超5个赞
我遵循了沃尔克的建议,并使用了一个渠道来解决问题。
func Read(url string, timeout time.Duration) (res *Response) {
done := make(chan bool) // A channel
resChan := make(chan *Response)
go func() {
resChan <- Get(url)
done <- true
}()
select {
case <-done:
res = &Response{}
case <-time.After(timeout):
res = &Response{"Gateway timeout\n", 504}
}
return
}
现在,不能同时写入 res。它将是超时或返回的值Get(url)。
- 2 回答
- 0 关注
- 177 浏览
添加回答
举报
0/150
提交
取消