2015-02-09 4 views
3

Как справиться с множеством ошибок в Go?Более сложная обработка ошибок в Go

Я смотрю на мой код и обнаружить, что она полна обработчиков ошибок:

err = result.Scan(&bot.BID, &bot.LANGUAGE, &bot.SOURCE) 
if err != nil { 
    log.Fatalf("result.Scan: %v", err) 
    return 
} 

fileName, err := copySourceToTemporaryFile(bot) 
if err != nil { 
    log.Fatalf("copySourceToTemporaryFile: %v", err) 
    return 
} 
... 

И много линий выглядеть так:

// do something 
// handle error 
// handle error 
// handle error 

// do something 2 
// handle error 
// handle error 
// handle error 

Могу ли я создать обработчик по умолчанию, который печатает ошибки и прекращает обработку, или, по крайней мере, вытеснить эту «ошибку-обработчик-мусор» из моей логики кода?

+0

Это выглядит некрасиво на первый (и позже), но я, случается, нравится вид ошибки ловли. Это действительно заставляет меня думать: «Что я должен делать в этом случае? Должен ли я сбой (смертельный), должен ли я продолжать использовать какой-либо другой метод/по умолчанию или я должен спросить пользователя». Если вы все равно выполняете 'log.Fatalf()', вы можете определить метод 'CrashIfErr (ошибка ошибки)' с простым вызовом 'log.Fatalf()'. BTW: нет необходимости в 'return' после' log.Fatalf() '. – topskip

ответ

5

Это напоминает мне о недавнем Errors are values Роба Пайка, а также Mr. Rob Pike taught me about practice of error handling in Go at GoCon 2014

Ключевой урок, однако, заключается в том, что ошибки являются значения и полная мощность языка программирования Go доступен для их обработки ,

Стоит подчеркнуть, что независимо от конструкции, важно, чтобы программа проверила ошибки, однако они были выставлены. Здесь речь идет не о том, как избежать ошибок, а об использовании языка для обработки ошибок с изяществом.

Один из методов заключается в определении объекта называется errWriter:

type errWriter struct { 
    w io.Writer 
    err error 
} 

Метод write вызывает метод Write подстилающего Writer и записывает первую ошибку для будущей ссылки:

func (ew *errWriter) write(buf []byte) { 
    if ew.err != nil { 
     return 
    } 
    _, ew.err = ew.w.Write(buf) 
} 

Как только возникает ошибка, метод write становится не-оператором, но значение error сохраняется.

Учитывая тип errWriter и способ его записи, приведенный выше код может быть переработан:

ew := &errWriter{w: fd} 
ew.write(p0[a:b]) 
ew.write(p1[c:d]) 
ew.write(p2[e:f]) 
// and so on 
if ew.err != nil { 
    return ew.err 
} 
+2

Я читал это раньше. Что делать, если методы, которые я вызываю, возвращают не только ошибки, но и структуры разных типов? –

1

Если error является «реальным», вы должны (должны) справиться с этим, если вы этого не сделаете хотите неожиданные паники во время выполнения.

В дополнение ответ VonC по поводу errWriter техники, есть еще случаи, когда вы можете уменьшить кода обработки ошибок:

Это те случаи, когда вы знаете, что даже если функция или метод может возвращать error, он не будет (например, вы поставляете параметры из исходного кода, который, как вы знаете, будет работать). В этих случаях вы (или автор библиотеки) можете предоставить помощникам функции (или методы), которые не возвращают error, но повышают панику во время выполнения, если это все еще происходит.

В качестве примера можно привести пакеты template и regexp: если вы предоставите допустимый шаблон или регулярное выражение во время компиляции, вы можете быть уверены, что их можно всегда анализировать без ошибок во время выполнения.По этой причине пакет template предоставляет функцию Must(t *Template, err error) *Template, а пакет regexp обеспечивает функцию MustCompile(str string) *Regexp: они не возвращают error, так как их предполагаемое использование является гарантией того, что вход гарантирован.

Примеры:

// "text" is a valid template, parsing it will not fail 
var t = template.Must(template.New("name").Parse("text")) 

// `^[a-z]+\[[0-9]+\]$` is a valid regexp, always compiles 
var validID = regexp.MustCompile(`^[a-z]+\[[0-9]+\]$`) 
+1

Мне нравится подход 'Mustxxx', который может упростить управление ошибками и уточнить ожидания. +1 – VonC

Смежные вопросы