Golang返回nil不返回nil

时间:2018-12-22 02:03:36

标签: go error-handling

我创建了一个自定义错误类型来包装错误,以便在Golang中更轻松地进行调试。当有打印错误时它可以工作,但是现在引起了恐慌。

Demo

type Error struct {
    ErrString string
}

func (e *Error) Error() string {
    return e.ErrString
}

func Wrap(err error, str string) *Error {
    if err == nil {
        return nil
    }
    e := &Error{
        ErrString: str + err.Error(),
    }
    return e
}

当我调用一个函数时,它不会返回错误,我仍然应该能够包装该错误。

预期的行为是,如果错误为nil,则应该将其忽略,不幸的是,情况恰恰相反。

func foo() error {
    err := bar()
    return Wrap(err, "bar called")
}

func bar() error {
    return nil
}

func main() {
    err := foo()
    if err != nil {
        fmt.Printf("Found error %v\n",err)
        return
    }
    fmt.Println("No Errors")
}

我希望它能打印No errors。相反,即使错误为nil,它也会打印Found error <nil>

3 个答案:

答案 0 :(得分:3)

if err != nil

正在将err变量与nil error进行比较,但实际上是nil *Error

将代码更改为

err:=foo()
var  nilerror *Error = nil
if err != nilerror {
    fmt.Printf("Found error %v\n",err)
    return
}
fmt.Println("No Errors")

产生预期的结果。

答案 1 :(得分:2)

  

type error

     

错误内置接口类型是用于   表示错误情况,nil值表示否   错误。

type error interface {
    Error() string 
}

err类型interface的{​​{1}}的值不是nil。它是类型error的值nil。实际上,*main.Errorerr != nil && err.(*Error) == nil


例如,

true

游乐场:https://play.golang.org/p/nwNRa2sNwj0

输出:

package main

import (
    "fmt"
)

func error1() {
    err := foo()
    fmt.Printf("%T %v %v %v\n", err, err, err == nil, err.(*Error) == nil)
    if err != nil {
        fmt.Printf("Found error %v\n", err)
        return
    }
    fmt.Println("No Errors")
}

func error2() {
    err := foo()
    fmt.Printf("%T %v %v %v\n", err, err, err == nil, err.(*Error) == nil)
    if err != nil && err.(*Error) != nil {
        fmt.Printf("Found error %v\n", err)
        return
    }
    fmt.Println("No Errors")
}

type Error struct {
    ErrString string
}

func (e *Error) Error() string {
    return e.ErrString
}

func Wrap(err error, str string) *Error {
    if err == nil {
        return nil
    }
    e := &Error{
        ErrString: str + err.Error(),
    }
    return e
}

func foo() error {
    err := bar()
    return Wrap(err, "bar called")
}

func bar() error {
    return nil
}

func main() {
    error1()
    fmt.Println()
    error2()
}

答案 2 :(得分:0)

由于您的Error类型实现了error接口,所以最简单的解决方案是在error中返回一个Wrap()

func Wrap(err error, str string) error {
    if err == nil {
        return nil
    }
    e := &Error{
        ErrString: str + err.Error(),
    }
    return e
}