Go语言的三个雷区
来源:互联网 发布:大数据是什么专业 编辑:程序博客网 时间:2024/05/16 07:42
下面的例子都是在Kubernetes代码中的,而且据我所知,都不止一次地通过了代码审查。
1. 循环中变量的作用域问题
观察下面的代码,预测其功能是什么?
func print(pi *int) { fmt.Println(*pi) }for i := 0; i < 10; i++ { defer fmt.Println(i) defer func(){ fmt.Println(i) }() defer func(i int){ fmt.Println(i) }(i) defer print(&i) go fmt.Println(i) go func(){ fmt.Println(i) }()}
答案:
func print(pi *int) { fmt.Println(*pi) }for i := 0; i < 10; i++ { defer fmt.Println(i) // OK; prints 9 ... 0 defer func(){ fmt.Println(i) }() // WRONG; prints "10" 10 times defer func(i int){ fmt.Println(i) }(i) // OK defer print(&i) // WRONG; prints "10" 10 times go fmt.Println(i) // OK; prints 0 ... 9 in unpredictable order go func(){ fmt.Println(i) }() // WRONG; totally unpredictable.}for key, value := range myMap { // Same for key & value as i!}
大家都认为这些变量能正常工作,但实际上,Go语言随着迭代会重用相同的内存。这意味着,你永远不能让key,value,i的值在循环外使用。匿名函数func() { /* do something with i */ }
(一个“闭包”)是解决这个问题的巧妙办法,其实闭包传递的是引用(地址),恰恰是引起这个问题的元凶。
2. Nil接口并不是有Nil指针的接口
type Cat interface { Meow()}type Tabby struct {}func (*Tabby) Meow() { fmt.Println("meow") }func GetACat() Cat { var myTabby *Tabby = nil // Oops, we forgot to set myTabby to a real value return myTabby}func TestGetACat(t *testing.T) { if GetACat() == nil { t.Errorf("Forgot to return a real cat!") }}
猜到了吗?上面的代码不会发现Nil指针!
一个interface,其内部的值包括type和value。只有当两个值都是空{type:nil,value:nil},我们才认为该interface==nil成立。由于赋值的方式,导致myTabby的type不为空{*Tabby,nil},因此该Cat接口指针不为nil,即使value的pointer==nil。
这是因为,接口作为一个指针,所以GetACat实际上将一个指针返回给了空指针。永远不要写上面这种代码,这样你的同事会很高兴的。用错误值来代替更好。(http://golang.org/doc/faq#nil_error)
3. 有害的变量名
var ErrDidNotWork = errors.New("did not work")func DoTheThing(reallyDoIt bool) (err error) { if reallyDoIt { result, err := tryTheThing() if err != nil || result != "it worked" { err = ErrDidNotWork } } return err}
上面的函数永远都会返回一个Nil错误,因为内部的err变量覆盖了函数的作用域变量,使用 var result string
,不使用:=
可以解决这个问题。
原文:The Three Go Landmines.markdown
作者:lavalamp 翻译:赖信涛 责编:仲培艺
0 0
- Go语言的三个雷区
- 领导力的三个雷区
- 使用Go 语言的三个原因
- GDI+的雷区
- Go学习笔记:有意思的三个点儿
- GO语言的并发
- Go!漂亮的语言!
- Go语言的崛起
- Go语言的坑
- go语言的指针
- go 语言的了解
- Go语言的关键字
- Go语言的特性
- go语言的模板
- Go语言的接口
- go语言的初探
- Go语言的学习
- go语言的认识
- C++实验4:项目六 百钱买百鸡
- Failed to load JavaHL Library的解决办法
- Python正则
- Using neural nets to recognize handwritten digits
- 禁止开头输入空格
- Go语言的三个雷区
- log4j.properties配置文件
- MySQL数据库锁介绍
- CTF PWN 远程payload
- JQuery的Flexigrid的API使用
- Windows平台搭建LaTeX撰写环境[支持中文]
- 对中断的理解
- 用户空间和内核空间通讯之【Netlink 上、中、下】
- c++作业3—项目4