Оригинальная ссылка:woohoo.fly snow.org/2019/01/01/…
Публичный аккаунт WeChat: flysnow_org
Из-за неправильного дизайна языка Go (golang), я полагаю, многие люди столкнулись с этим.Это заставляет вызывающую сторону обрабатывать ошибку, возвращая значение, либо вы игнорируете ее, либо обрабатываете ее (обработка также может продолжать возвращаться к звонящий), для метода проектирования golang мы напишем много кода в кодеif
суждение для принятия решения.
func main() {
conent,err:=ioutil.ReadFile("filepath")
if err !=nil{
//错误处理
}else {
fmt.Println(string(conent))
}
}
Этот тип кода очень распространен в нашем кодировании, в большинстве случаевerror
обаnil
, то есть ошибок нет, но нетnil
Когда это означает, что произошла ошибка, нам нужно с ней справиться.
интерфейс ошибки
error
По сути интерфейс, встроенный, давайте посмотрим на его определение
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
У него есть только один методError
, пока этот метод реализован, он реализованerror
. Теперь попробуем определить ошибку самостоятельно.
type fileError struct {
}
func (fe *fileError) Error() string {
return "文件错误"
}
пользовательская ошибка
пользовательскийfileError
Тип, реализованныйerror
интерфейс. Теперь протестируйте его, чтобы увидеть эффект.
func main() {
conent, err := openFile()
if err != nil {
fmt.Println(err)
} else {
fmt.Println(string(conent))
}
}
//只是模拟一个错误
func openFile() ([]byte, error) {
return nil, &fileError{}
}
Мы запускаем смоделированный код и видим文件错误
объявление о.
В реальном использовании мы можем столкнуться со многими ошибками. Разница между ними заключается в том, что информация об ошибке отличается. Один из способов — определить тип ошибки для каждой ошибки, как указано выше, но это слишком хлопотно. мы обнаруживаемError
То, что возвращается, на самом деле является строкой, мы можем изменить ее, чтобы можно было установить строку.
type fileError struct {
s string
}
func (fe *fileError) Error() string {
return fe.s
}
Что ж, после этого преобразования мы можем объявитьfileError
При настройке текста ошибки, который будет запрашиваться, он может удовлетворить наши различные потребности.
//只是模拟一个错误
func openFile() ([]byte, error) {
return nil, &fileError{"文件错误,自定义"}
}
Что ж, да, мы достигли своей цели. Теперь мы можем сделать его более общим, например, изменитьfileError
Имя, а затем создайте функцию помощника, чтобы мы могли создавать разные типы ошибок.
//blog:www.flysnow.org
//wechat:flysnow_org
func New(text string) error {
return &errorString{text}
}
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
Стать выше, мы можем пройтиNew
функция, чтобы помочь нам создавать различные ошибки, которые мы часто используемerrors.New
Функция была разработана нашим анализом шаг за шагом.Теперь все ошибаются по поводу встроенных ошибок языка Go (golang).error
С четким пониманием.
существующие проблемы
Хотя оформление ошибок в языке Go очень лаконичное, для нас, разработчиков, его явно недостаточно, например, нам нужно знать больше информации об ошибках, в каком файле, какая строка кода? Только так мы сможем легче обнаружить проблему.
Также, например, мы хотимerror
Добавьте дополнительную информацию, а затем вернитесь, например, как в приведенном выше примере, как мы это делаем? мы можем только пройтиError
метод, выньте исходное сообщение об ошибке, затем соедините его самостоятельно, а затем используйтеerrors.New
Функция генерирует новый возврат ошибки.
Если мы занимались разработкой Java раньше, мы знаем, что исключения Java могут быть вложенными, то есть благодаря этому мы можем легко узнать основную причину ошибки, потому что исключения Java возвращаются слой за слоем вложенными, независимо от того, сколько упаковка проходит через середину, мы можем пройтиcause
Найдите основную причину ошибки.
Решать проблему
Если мы хотим решить вышеуказанные проблемы, то сначала мы должны продолжать расширять нашиerrorString
и добавьте еще несколько полей для хранения дополнительной информации. Например, мы хотим записать информацию о стеке.
type stack []uintptr
type errorString struct {
s string
*stack
}
Добро пожаловать в публичный аккаунт WeChatflysnow_org
или сайт блогаwww.flysnow.org/Ознакомьтесь с другими оригинальными статьями.
С информацией о стеке хранилищаstack
Поле, когда мы создаем ошибку, мы можем хранить информацию стека вызовов в этом поле.
//blog:www.flysnow.org
//wechat:flysnow_org
func callers() *stack {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(3, pcs[:])
var st stack = pcs[0:n]
return &st
}
func New(text string) error {
return &errorString{
s: text,
stack: callers(),
}
}
Идеальное решение, теперь, если мы решим его снова, как насчет проблемы с добавлением некоторой информации к существующей ошибке? Я считаю, что у каждого должна быть идея.
type withMessage struct {
cause error
msg string
}
func WithMessage(err error, message string) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: message,
}
}
использоватьWithMessage
функция, для оригиналаerror
Под упаковкой может появиться новая ошибка с информацией об упаковке.
Рекомендуемое решение
Мы решаем проблему выше, принятый метод более знаком? Особенно глядя на исходный код, да, этоgithub.com/pkg/errors
Исходный код для этой библиотеки обработки ошибок.
Поскольку ошибки, предоставляемые языком Go, настолько просты, что мы не можем лучше справиться с проблемами или даже предоставить нам более полезную информацию для обработки ошибок, поэтому было создано так много библиотек для обработки ошибок.github.com/pkg/errors
Он относительно прост и обладает очень мощными функциями, что было одобрено большим количеством разработчиков и многими пользователями.
Его использование очень простое, если мы хотим сгенерировать новую ошибку, мы можем использоватьNew
Функция, вызвавшая ошибку, имеет собственную информацию о стеке вызовов.
func New(message string) error
Если есть существующийerror
, нам нужно снова его завернуть, на этот раз на выбор три функции.
//只附加新的信息
func WithMessage(err error, message string) error
//只附加调用堆栈信息
func WithStack(err error) error
//同时附加堆栈和信息
func Wrap(err error, message string) error
На самом деле приведенная выше упаковка очень похожа на упаковку исключений в Java.error
, по фактуCause
, основной причиной ошибки, упомянутой в предыдущей главе, являетсяCause
. Итак, эта библиотека обработки ошибок предоставляет намCause
Функции позволяют нам добраться до основной причины ошибки.
func Cause(err error) error {
type causer interface {
Cause() error
}
for err != nil {
cause, ok := err.(causer)
if !ok {
break
}
err = cause.Cause()
}
return err
}
использоватьfor
Цикл продолжает находить самый фундаментальный (нижний)error
.
Мы упаковали и собрали вышеуказанные ошибки, так как же нам распечатать такую информацию, как стек, хранящийся в них, причину ошибки и т.д.? На самом деле типы ошибок этой библиотеки обработки ошибок реализованыFormatter
интерфейс, мы можем пройтиfmt.Printf
Функция выводит соответствующее сообщение об ошибке.
%s,%v //功能一样,输出错误信息,不包含堆栈
%q //输出的错误信息带引号,不包含堆栈
%+v //输出错误信息和堆栈
Если выше указан тип ошибки переноса цикла, эти ошибки будут выведены рекурсивно.
резюме
с помощью этогоgithub.com/pkg/errors
Библиотека ошибок, мы можем собрать больше информации, может облегчить нам поиск проблемы.
Собранную нами информацию можно не только выводить в консоль, но и использовать в виде лога, используя вывод в соответствующийLog
Журнал для легкого анализа проблемы.
Говорят, что эта библиотека будет добавлена в стандартный SDK Golang. Я с нетерпением жду этого. Если она будет добавлена, она должна быть дополнением к текущей стандартной библиотеке.errors
этот пакет.
Эта статья является оригинальной статьей, перепечатайте и укажите источник, добро пожаловать на сканирование кода и обратите внимание на общедоступный номер
flysnow_org
или сайт asfwww.flysnow.org/, и впервые прочитал последующие замечательные статьи. Если вы считаете, что это хорошо, пожалуйста, нажмите «красивый» в правом нижнем углу статьи, спасибо за вашу поддержку.