2013-03-17 4 views
2

Я читал this blog post, но я все еще не убежден. Я точно знаю, что делать, чтобы получить пользовательские ошибки, которые я могу вернуть из своих функций и обрабатывать вне их.Пользовательская обработка ошибок в Go

Это то, что я сейчас делаю:

func doSomething() int { 
    x := 0 
    // Do something with x. 
    ... 
    if somethingBadHappened { 
     return -1 
    } 
    if somethingElseBadHappened { 
     return -2 
    } 
    return x 
} 

Это то, что я хотел бы делать:

func doSomething() int, ? { 
    ... 
    if somethingBadHappened { 
     return ?, err 
    } 
    if somethingElseBadHappened { 
     return ?, err2 
    } 
    return x, nil 
} 

Но я точно не знаю, как и что замените эти вопросительные знаки.

ответ

3

Я бы превратить

func doSomething() int, ? { 
     ... 
     if somethingBadHappened { 
       return ?, err 
     } 

     if somethingElseBadHappened { 
       return ?, err2 
     } 

     return x, nil 
} 

в

func doSomething() (r int, err error) { 

     ... 

     if somethingBadHappened { 
       err = err1 // Whatever satisfies the `error` interface 
       return 
     } 

     if somethingElseBadHappened { 
       err = err2 // dtto 
       return 
     } 

     return x, nil 
} 

IOW, на месте называют это является идиоматическим * игнорировать, никогда не использовать или не полагаться на любое другое возвращаемое значение, если err! = nil, поэтому просто не волнует, если r выше было присвоено некоторое промежуточное значение или нет.

(*) В первом приближении, то есть если не указано иное. Например. io.Reader явно заявляет, что может вернуть оба err == io.EOF и достоверные данные, в то же время:

Когда Чтение обнаруживает ошибку или конца-файла состояние после успешного чтения п> 0 байт, она возвращает число чтение байтов. Он может возвращать (не-ниль) ошибку из одного и того же вызова или возвращать ошибку (и n == 0) из последующего вызова. Экземпляр этого общего случая заключается в том, что Reader, возвращающий ненулевое число байтов в конце входного потока, может возвращать либо err == EOF, либо err == nil. Следующий Read должен возвращать 0, EOF независимо.

+0

Хм. Чтобы удовлетворить интерфейс ошибки, мне просто нужно создать какой-то новый тип структуры с строковой переменной в нем и создать реализацию ошибки, правильно? Или есть еще более простой способ? –

+0

@jnml - не следует «возвращать x, nil' быть' return r, nil'? –

+0

@ Ekkehard.Horner: Это может быть 'return r, nil' тоже, но не обязательно. В OP 'x' стоит локальная переменная, и она также имеет здесь значение. В общем, последняя строка может быть либо 'return', либо' reuturn expr1, expr2'. – zzzz

7

Вам не нужно возвращать int, если вы этого не хотите. Вы можете сделать что-то вроде:

func doSomething() error { 
    ... 
    if somethingBadHappened { 
     return errors.New("something bad happened") 
    } 
    if somethingElseBadHappened { 
     return errors.New("something else bad happened") 
    } 
    return nil 
} 

или если вы хотите, чтобы вернуть Интс

func doSomething() (int, error) { 
    ... 
    if somethingBadHappened { 
     return -1, errors.New("something bad happened") 
    } 
    if somethingElseBadHappened { 
     return -2, errors.New("something else bad happened") 
    } 
    return x, nil 
} 

обязательно import "errors" в верхней части.

Если вы хотите проверить, есть ли у вас ошибка, вы можете сделать

x, err := doSomething() 
if err != nil { 
    log.Println(err) 
}