美文网首页js css htmlgo
Go变量遮蔽导致的意外错误

Go变量遮蔽导致的意外错误

作者: Go语言由浅入深 | 来源:发表于2022-12-27 16:23 被阅读0次

阳了快一个星期了,没有更新文章。也在思考发些什么内容比较实用。之前发的一些文章都是比较基础的适合普通的Go开发人员交流学习。之前看到国外有人在整理Go的常见错误,这个也是每个编程人都希望掌握的,毕竟谁都不想犯错。
现在网上也可以阅读原版内容了,这里我也把相关的一些内容翻译下,供大家参考。


今天要介绍的第一个易犯错误就是,变量作用域导致的。

变量的作用域是指变量可以被引用的范围。换句话说,是应用程序中变量名绑定有效的部分。在Go语言中,在代码块中声明的变量名可以在内部代码块中重新声明。这个原理被称为变量遮蔽,容易犯常见错误。

下面的示例显示了由于变量遮蔽而产生的意外副作用。它以两种不同的方式创建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

1、申明一个client变量
2、如果tracing是true创建HTTP客户端。在这里第一步定义的client变量被遮蔽。
3、创建一个默认http客户端。这里也会发生变量的遮蔽。
在这个例子中,我们首先申明client变量。然后在内部代码块if...else..中使用短变量申明操作符(:=)将函数返回值赋给内部变量client,而不是外部client变量。因此,外部变量client还是初始值nil。

注意:这段代码能编译通过,是因为内部client变量在log.Println中使用了。否则,编译会报错例如client declared and not used.

我们该如何确保最初的client变量被正确赋值呢?

第一种方法:在内部代码块中使用临时变量,如下所示:

var client *http.Client
if tracing {
    c, err := createClientWithTracing()    ❶
    if err != nil {
        return err
    }
    client = c                                           ❷
} else {
    // Same logic
}

1、创建临时变量c。
2、将临时变量值赋给client。
这里将函数调用结果赋值给脸是变量c,它的作用域只在if...else...代码块范围内。然后将值赋给client。同时对else部分做相同处理。

第二种方法:在内层代码块里面使用赋值操作符(=),将函数返回值直接赋给client变量。但是,这里需要定义error变量,因为赋值操作符仅作用于已经定义的变量。例如:

var client *http.Client
var err error                                                ❶
if tracing {
    client, err = createClientWithTracing()    ❷
    if err != nil {
        return err
    }
} else {
    // Same logic
}

1、申明err变量。
2、使用赋值操作符将返回的*http.Client值直接赋给client变量。
这里取代传值给临时变量,而是直接将结果传给client。

以上两种方式都有效。主要区别在第二种方法只需要一次赋值,使代码便于阅读。同时,使用第二种方式,我们可以在if/else语句之外实现错误处理。

if tracing {
    client, err = createClientWithTracing()
} else {
    client, err = createDefaultClient()
}
if err != nil {
    // Common error handling
}

当在内部代码块中重新声明变量名时,就会发生变量遮蔽,但我们看到这种做法容易出错。禁止变量遮蔽的规则取决于个人喜好。例如,有时重用现有的变量名(如err用于错误)会很方便。然而,一般来说,我们应该保持谨慎,因为我们现在知道可能会面临这样的场景:代码可编译完成,但接收值的变量不是预期的值。

相关文章

  • Go变量遮蔽导致的意外错误

    阳了快一个星期了,没有更新文章。也在思考发些什么内容比较实用。之前发的一些文章都是比较基础的适合普通的Go开发人员...

  • go语言-error 简版记录

    go语言中错误分为error和panic error 1.错误变量 2.自定义错误类型 3.错误类型返回 pani...

  • go空白符

    go不同其他语言当变量未被引用时则会编译错误 变量未被使用 命名空白变量如果有些变量我们声明了,不会使用但是还的必...

  • go语言——数据运算陷阱

    go语言规定不允许在整数型变量和浮点型变量之间进行任何数学运算。错误例子如下: 改正结果如下:

  • Golang变量遮蔽——Shadowing

    在golang中,我们经常会用:=来声明变量,这很方便但也会带来一些问题。当变量遇到作用域时就容易产生shadow...

  • go 安装配置(一)

    基本 安装gobrew install go 查看go环境变量go ev 设置go环境变量vim .bash_pr...

  • Go之旅-变量

    Go语言变量有固定的数据类型,决定了变量内存的长度和存储格式。Go变量只能修改变量值,不能改变变量的数据类型。Go...

  • golang的helloworld

    go语言初识 go语言的变量

  • GO语言基础(六)

    定义变量 Go语言里面定义变量有很多种方式。使用var关键字是Go最基本的定义变量方式,与C语言不同的是Go把变量...

  • 内存逃逸

    在C中 val是栈上的局部变量,返回其指针是明显错误的。 而go的编译器则会进行逃逸分析,如下代码 使用 go t...

网友评论

    本文标题:Go变量遮蔽导致的意外错误

    本文链接:https://www.haomeiwen.com/subject/kspnqdtx.html