Голанг, возвращающий ноль, не возвращает ноль - PullRequest
0 голосов
/ 22 декабря 2018

Я создал собственный тип ошибок, чтобы обернуть ошибки для упрощения отладки в Golang.Это работает, когда есть ошибки, чтобы напечатать, но теперь это вызывает панику.

Демонстрация

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() {
    err := foo()
    if err != nil {
        fmt.Printf("Found error %v\n",err)
        return
    }
    fmt.Println("No Errors")
}

Я ожидаю, что она напечатает No errors.Вместо этого он печатает Found error <nil>, даже если ошибка равна нулю.

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018
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")

Дает прогнозируемый результат.

0 голосов
/ 22 декабря 2018

Поскольку ваш тип Error реализует интерфейс error, самое простое решение - вернуть error в Wrap():

func Wrap(err error, str string) error {
    if err == nil {
        return nil
    }
    e := &Error{
        ErrString: str + err.Error(),
    }
    return e
}
0 голосов
/ 22 декабря 2018

ошибка типа

Тип интерфейса встроенной ошибки - это обычный интерфейс для представления состояния ошибки, при этом значение nil не представляет ошибки.

type error interface {
    Error() string 
}

Значение err из interface типа error не равно нулю.Это значение nil типа *main.Error.Фактически, err != nil && err.(*Error) == nil - это true


Например,

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()
}

Детская площадка: https://play.golang.org/p/nwNRa2sNwj0

Выход:

*main.Error <nil> false true
Found error <nil>

*main.Error <nil> false true
No Errors
...