Golang中error的一个坑

Posted end

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang中error的一个坑相关的知识,希望对你有一定的参考价值。

err != nil

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

思考如下代码:

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。

以上是关于Golang中error的一个坑的主要内容,如果未能解决你的问题,请参考以下文章

golang-错误处理

【避坑指南】golang中使用int类型导致数据溢出

Golang学习 - strconv 包--数据类型转换

golang的哪些坑爷事: package实践

Golang 入门常见初级坑(备忘录)

golang thrift 总结一下网络上的一些坑