分享
  1. 首页
  2. 文章

Golang 博主走过的有关 error 的一些坑

deepzz · · 1106 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Desc:为什么值为 nil 的 error 却不等于 nil

本片文章用来记录我在 Golang 开发学习过程中遇到的有关 error 的一些坑。或许你也遇到,或许你能在这里找到答案。当然通过 error 的例子,你也应该联想到其它场景。

err != nil

第一个问题是:为什么值为 nil 的 error 却不等于 nil?

<!--more-->

思考如下代码:

package main
import (
 "errors"
 "fmt"
)
type Err struct {
 err string
}
func (e *Err) Error() string {
 return e.err
}
func returnErr() *Err {
 return nil
}
func main() {
 var err error
 err = returnErr()
 fmt.Println(err, err != nil)
}

首先 returnErr() 返回了一个值为 nil 的 *Err,然后赋值给了 err,那么 fmt 会打印什么结果?是不是:

<nil> false

错,它会打印 <nil> true。当时自己也是没有头绪,学艺不精,问过大神才知道,这是接口 interface 造成的。具体可以查看 官网 FAQ

简单说,interface 被两个元素 value 和 type 所表示。只有在 value 和 type 同时为 nil 的时候,判断 interface == nil 才会为 true。而 err = returnErr() 这个过程中,虽然 value 为 nil,但 type 却为 *Err。

如何解决这个问题呢?在我看来只能从根源上着手,两种方式:

  1. 不要将该结果赋给一个接口变量。如,将 err = returnErr()
    改成 err1 := returnErr(),这样就可以避免造成的干扰。
  2. 不要让函数返回自定义类型,如,*Err。应该将错误包装过滤为 error,如:

    func Err() (err error) {
     if e := returnErr(); e != nil {
     return e
     }
     return
    }

err == nil

为什么还有 err == nil的问题呢?这个问题是我看查看标准库源码的时候发现的,其中有这么一段:

func (e *AddrError) Error() string {
 if e == nil { // 请注意,为什么这里会判断是否为 nil
 return "<nil>"
 }
 s := e.Err
 if e.Addr != "" {
 s = "address " + e.Addr + ": " + s
 }
 return s
}

为什么会再次去判断 e == nil,当时很是费解。众所周知,方法(姑且这样说)和变量是存储在不同区域的,当我们用一个空指针类型的变量(如,var e *AddrError)调用方法时,该方法是会执行的,只有在执行该空指针变量的解指针操作时,才会 panic。

下面是一个例子:

// Package main provides ...
package main
import "fmt"
func main() {
 var e *Err
 e.Print()
 e.Printf()
 e.Println()
}
type Err struct {
 err string
}
func (e *Err) Print() {
 fmt.Println("e.Print run")
}
func (e *Err) Printf() {
 fmt.Println(e.err)
}
func (e Err) Println() {
 fmt.Println("e.Println run")
}

1、e.Print() 是完全可以执行的,没有解指针操作。

2、e.Printf() 在调用 e.err 的时候,发生了解指针操作,故会 panic。

3、e.Println() 由于接受者是 Err 而不是 *Err,Golang 内部在调用该函数时,会自动解指针,故会 panic。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:deepzz

查看原文:Golang 博主走过的有关 error 的一些坑

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1106 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏