d****n 发帖数: 1637 | 1 献给gopher们,俺还没踩到,不过惊出一身冷汗。希望对其他gopher有用
http://studygolang.com/articles/5188
坑(s)
每种编程语言都有自己的专属坑(s),Go虽出身名门,但毕竟年轻,坑也不少,在error
处理这块也可以列出几个。
1、 Go FAQ:Why is my nil error value not equal to nil?
type MyError string
func (e *MyError) Error() string {
return string(*e)
}
var ErrBad = MyError("ErrBad")
func bad() bool {
return false
}
func returnsError() error {
var p *MyError = nil
if bad() {
p = &ErrBad
}
return p // Will always return a non-nil error.
}
func main() {
err := returnsError()
if err != nil {
fmt.Println("return non-nil error")
return
}
fmt.Println("return nil")
}
上面的输出结果是”return non-nil error”,也就是说returnsError返回后,err !=
nil。err是一个interface类型变量,其underlying有两部分组成:类型和值。只有这
两部分都为nil时,err才为nil。但returnsError返回时将一个值为nil,但类型为*
MyError的变量赋值为err,这样err就不为nil。解决方法:
func returnsError() error {
var p *MyError = nil
if bad() {
p = &ErrBad
}
return nil
}
2、switch err.(type)的匹配次序
试想一下下面代码的输出结果:
type MyError string
func (e MyError) Error() string {
return string(e)
}
func Foo() error {
return MyError("foo error")
}
func main() {
err := Foo()
switch e := err.(type) {
default:
fmt.Println("default")
case error:
fmt.Println("found an error:", e)
case MyError:
fmt.Println("found MyError:", e)
}
return
}
你可能会以为会输出:”found MyError: foo error”,但实际输出却是:”found an
error: foo error”,也就是说e先匹配到了error!如果我们调换一下次序呢:
... ...
func main() {
err := Foo()
switch e := err.(type) {
default:
fmt.Println("default")
case MyError:
fmt.Println("found MyError:", e)
case error:
fmt.Println("found an error:", e)
}
return
}
这回输出结果变成了:“found MyError: foo error”。
也许你会认为这不全是错误处理的坑,和switch case的匹配顺序有关,但不可否认的
是有些人会这么去写代码,一旦这么写,坑就踩到了。因此对于通过switch case来判
定error type的情况,将error这个“通用”类型放在后面或去掉。 |
f*******t 发帖数: 7549 | 2 我踩到了第一个坑的变种,实在恶心。
type A struct {}
func foo() *A {
return nil
}
AssertNil(interface{} o) {
if o != nil {
panic()
}
}
AssertNotNil(foo()) 会panic,因为o是(*A)(nil),跟无类型的nil不等 |
d****n 发帖数: 1637 | 3 这坑我要花好多时间才能跳出来。
谢谢分享
【在 f*******t 的大作中提到】 : 我踩到了第一个坑的变种,实在恶心。 : type A struct {} : func foo() *A { : return nil : } : AssertNil(interface{} o) { : if o != nil { : panic() : } : }
|
t***t 发帖数: 6066 | |
T******7 发帖数: 1419 | 5 1 很好理解。本来就是一個interface.两部分呢。go programming lang那本书上写的
也很清楚
先在的小孩,真以为一周看看tutorial就可以写production code了?
不看2本书就写代码就是耍流氓阿。
过去老子学c++没看4,5本书都不敢说会写c++ |
r******t 发帖数: 250 | 6 看一周已写了上万行 production code,不过仔细想想确实有些困惑的地方
【在 T******7 的大作中提到】 : 1 很好理解。本来就是一個interface.两部分呢。go programming lang那本书上写的 : 也很清楚 : 先在的小孩,真以为一周看看tutorial就可以写production code了? : 不看2本书就写代码就是耍流氓阿。 : 过去老子学c++没看4,5本书都不敢说会写c++
|
r******t 发帖数: 250 | 7 其实就是试图写这样的程序
a := nil
如果 nil 可以 polymorphic 那么接下来就有一些困惑的事情
a = &A{...}
a = &B{...}
Go 通过 typed 'nil' 避免了这个问题 但是悄悄发生的
另外发现 Go 还可以避免 a := nil 的问题 很欣慰 |