温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么解决Go语言的read读取错误

发布时间:2021-11-01 14:40:32 来源:亿速云 阅读:541 作者:iii 栏目:编程语言

这篇文章主要讲解了“怎么解决Go语言的read读取错误”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决Go语言的read读取错误”吧!

情景描述

代码中需要实现一个客户端与服务器的数据重传机制,通过write写数据给服务器,read读取服务器返回。一旦中途发生错误,每隔1s就尝试重新写读数据。当超过上下文时间,重传失败。重传实现代码retry如下。

func retry(ctx context.Context) (data string, err error) {  LOOP:  for i:=1;;i++{   err = write()   if err == nil{    res, err := read()    if err == nil{     data = string(res)     return data, err    }   }    log.Printf("change data failed, err: %v, retry times : %d\n", err, i)    select {   case <-ctx.Done():    log.Printf("retry failed")    break LOOP   case <-time.After(1 * time.Second):   }  }  return "", err }

读写服务器数据函数和调用重传代码mock如下。

func write() error {  return nil }  func read() ([]byte, error) {  return []byte("hello world"), errors.New("this is a error") }  func main() {  ctx,_ := context.WithTimeout(context.Background(),5*time.Second)  _, _ = retry(ctx)  time.Sleep(10*time.Second) }

write返回err为nil,read有非nil返回。这种情况下,日志输出如下。

2020/07/05 09:30:57 change data failed, err: <nil>, retry times : 1 2020/07/05 09:30:58 change data failed, err: <nil>, retry times : 2 2020/07/05 09:30:59 change data failed, err: <nil>, retry times : 3 2020/07/05 09:31:00 change data failed, err: <nil>, retry times : 4 2020/07/05 09:31:01 change data failed, err: <nil>, retry times : 5 2020/07/05 09:31:02 retry failed

原因分析

可以看到的是,如预想的一样:当发生错误时,就重新尝试write和read。即重传机制生效。但是,日志中为何err会为nil,read方法的错误返回被吞掉了?

经过排查,发现原因就在于&mdash;&mdash;Go语法糖:=(短变量声明)的不当使用。

err = write()  if err == nil{   res, err := read()   if err == nil{    data = string(res)    return data, err   }  }   log.Printf("change data failed, err: %v, retry times : %d\n", err, i)

在retry中,err是已被声明的变量类型error。由于read返回的是两个变量,故小菜刀在此利用短变量声明res变量,接受read的第一个返回参数。但是,此举会改变err的作用范围:err成为了一个局部变量。什么意思呢?即此时的err被短变量声明所作用,成为了新声明对象,它只能作用于内部区域了。对于外部log.Printf而言,其引用到的err还是write方法生成的err对象。因此,即使read方法返回的err不为空,log.Printf打印的还是write方法的err结果,导致read的err内容被吞。

因此,为了避免此类错误发生,相应代码调整如下。

var res []byte  res, err = read()  if err == nil{   data = string(res)   return data, err  }

此时,当read返回err非nil时,日志打印如下。

2020/07/05 09:46:16 change data failed, err: this is a error, retry times : 1 2020/07/05 09:46:17 change data failed, err: this is a error, retry times : 2 2020/07/05 09:46:18 change data failed, err: this is a error, retry times : 3 2020/07/05 09:46:19 change data failed, err: this is a error, retry times : 4 2020/07/05 09:46:20 change data failed, err: this is a error, retry times : 5 2020/07/05 09:46:21 retry failed

感谢各位的阅读,以上就是“怎么解决Go语言的read读取错误”的内容了,经过本文的学习后,相信大家对怎么解决Go语言的read读取错误这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI