关于golang:100-Go-mistakes之意外的变量隐藏

68次阅读

共计 1555 个字符,预计需要花费 4 分钟才能阅读完成。

本文是对《100 Go Mistackes:How to Avoid Them》一书的翻译。因翻译程度无限,不免存在翻译准确性问题,敬请体谅

变量的作用域是指它的可见性。换句话说,程序中的名称在哪局部是无效的。在 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.Client
if 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.Client
var 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 谬误。然而,一般来说,咱们应该放弃审慎,因为咱们曾经看到咱们可能会面临这样一种谬误:代码能够编译,但可能不会对咱们冀望的变量进行赋值。在本章前面,咱们将看到该如何检测变量暗藏,以帮忙咱们发现可能的谬误。

正文完
 0