写点什么

「Go 易错集锦」意外的变量隐藏

作者:Go学堂
  • 2022-11-17
    北京
  • 本文字数:1385 字

    阅读完需:约 5 分钟

「Go易错集锦」意外的变量隐藏

从错误中学习,是一种了不起的能力。让自己从错误中成长。


变量的作用域是指它的可见性。换句话说,程序中的名称在哪部分是有效的。在 Go 中,在块中声明的变量名称可以在内部块中重新声明。这种被称为变量隐藏的原则很容易出现错误


在下面的例子中,我们将看到一个关于变量隐藏产生的 bug。我们将使用两种不同的方式创建一个 HTTP 客户端,具体取决于 tracing 布尔值:


var client *http.Client  ①if tracing {  client, err := createClientWithTracing()  ②  if err != nil {    return err  }  log.Println(client)}else {  client, err := createDefaultClient()  ③  if err != nil {    return err  }  log.Println(client)}
//use client
复制代码


① 生命一个 client 变量

② 使用带 tracing 的创建一个 HTTP 客户端,client 变量在该块内被隐藏了

③ 创建一个默认的 HTTP 客户端,client 变量在该模块依然被隐藏掉了。


首先,我们声明了一个 client 变量。然后,在两个内部块中,我们使用 := 操作符,也叫做短变量声明运算符。该操作符使用和开始的时候相同的名称创建了一个新的 client 变量;它不会为第①行中的client 变量赋值。因此,在该示例中,HTTP 客户端将始终是 nil 值。


注意:该代码之所以可以编译成功,是因为在 logging 调用中使用了内部变量 client。否则,我们就会有编译错误:client declared and not used。


我们如何确保给 client 赋值了呢?有两种不同的方法。第一种方法是在内部块中使用临时变量,像下面这样:

var client *http.Clientif tracing {  c, err := createClientWithTracing()  ①  if err != nil {    return err  }  client = c ②} else {  c, err := createDefaultClient()  if err != nil {    return err  }  client = c}// Use client
复制代码


① 创建了一个临时变量 c

② 将临时变量赋给变量 client 变量 c 的生命周期只在 if/else 块中。然后,我们将这些变量赋值给client


第二种方式是在内部块中使用赋值操作符( = )来将函数的返回值直接赋值给 client变量. 然而,它需要创建一个 error 变量. 因为赋值运算符仅在已声明变量时才起作用。


var client *http.Clientvar err error  ①if tracing {  client, err = createClientWithTracing() ②  if err != nil {    return err  }} else {  client, err = createDefaultClient()  if err != nil {    return err  }}
复制代码


① 声明变量 err

② 使用赋值操作符将返回来的 *http.Client 直接赋值给 client 变量.


在这个例子中,我们也将内部调用的结果赋值给了client。哪种方法最好呢?第一种方法在大多数情况下都是更方便的,但是没有强迫说要是用哪种方法。


当在内部块中将一个变量名重新声明时就会发生变量隐藏,我们已经看到这种做法很容易出错。应根据项目和上下文制定避免隐藏变量的规则。例如,有时候,重用现有的变量名可能会很方便,像 err 错误。然而,一般来说,我们应该保持谨慎,因为我们已经看到我们可能会面临这样一种错误:代码可以编译,但可能不会对我们期望的变量进行赋值。在本章后面,我们将看到该如何检测变量隐藏,以帮助我们发现可能的错误。


---特别推荐 ---

特别推荐:一个专注 go 项目实战、项目中踩坑经验及避坑指南、各种好玩的 go 工具的公众号。「Go 学堂 」,专注实用性,非常值得大家关注。点击下方公众号卡片,直接关注。关注送《100 个 go 常见的错误》pdf 文档。

发布于: 刚刚阅读数: 3
用户头像

Go学堂

关注

关注「Go学堂」,学习更多编程知识 2019-08-06 加入

专注Go编程知识、案例、常见错误及原理分析。意在通过阅读更多优秀的代码,提高编程技能。同名公众号「Go学堂」期待你的关注

评论

发布
暂无评论
「Go易错集锦」意外的变量隐藏_Go_Go学堂_InfoQ写作社区