- Оригинальный адрес:Part 31: Custom Errors
- Оригинальный автор:Naveen R
- Переводчик: хаки хаки Пожалуйста, укажите источник.
В прошлом уроке мы узнали оerror
как представлено и как обрабатывается стандартной библиотекойerror
. Мы также узнали, как извлечь больше из стандартной библиотеки.error
Информация.
В этом руководстве показано, как использовать наши собственные определенные в наших функциях и пакетах.error
, мы будем использовать те же методы, что и стандартная библиотека, чтобы предоставить информацию о наших настройках.error
Чтобы получить больше информации.
использоватьNew
функция создания пользовательскихerror
Создать пользовательскийerror
Самый простой способ - использоватьerrors
упаковкаNewфункция.
в нашем использованииNew
функция создания пользовательскихerror
Перед этим давайте сначала разберемся, как это реализовано. предоставлено нижепакет ошибоксерединаNew
реализация функции.
// Package errors implements functions to manipulate errors.
package errors
// New returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
Реализация очень проста.errorString
это строка с однимs
тип конструкции.error
интерфейсError
Метод заключается в использовании в строке 14errorString
Реализован приемник указателя.
строка 5New
Функция принимает строковый параметр, используя этот параметр для созданияerrorString
значение типа и вернуть его адрес, новыйerror
Это завершено.
Теперь мы знаемNew
Как работает функция, давайте использовать ее в наших собственных программах для создания пользовательскихerror
.
Мы создадим простую программу, которая вычисляет площадь круга и возвращает значение, если радиус отрицателен.error
.
package main
import (
"errors"
"fmt"
"math"
)
func circleArea(radius float64) (float64, error) {
if radius < 0 {
return 0, errors.New("Area calculation failed, radius is less than zero")
}
return math.Pi * radius * radius, nil
}
func main() {
radius := -20.0
area, err := circleArea(radius)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Area of circle %0.2f", area)
}
В приведенной выше программе мы проверяем, меньше ли радиус нуля в строке 10. Если это так, верните 0 и соответствующийerror
содержание. В строке 13, если радиус больше 0, вычислите площадь и верните значение какnil
изerror
.
В основной функции проверяем строку 19error
Этоnil
. если неnil
, вывести ошибку и вернуться, иначе вывести площадь области.
В этой программе радиус меньше нуля, поэтому она напечатает,
Area calculation failed, radius is less than zero
использоватьErrorf
заerror
добавить больше информации
Приведенная выше программа работает нормально, но если мы хотим напечатать точное сообщение об ошибке, это немного сложно. эта сценаfmt
упаковкаErrorf
Функции пригодятся. Эта функция принимает параметр строкового формата и возвращает строку в видеerror
значение .
давай попробуемErrorf
функция,
package main
import (
"fmt"
"math"
)
func circleArea(radius float64) (float64, error) {
if radius < 0 {
return 0, fmt.Errorf("Area calculation failed, radius %0.2f is less than zero", radius)
}
return math.Pi * radius * radius, nil
}
func main() {
radius := -20.0
area, err := circleArea(radius)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Area of circle %0.2f", area)
}
В приведенной выше программе строка 10 используетErrorf
, печатает фактическое значение радиуса, вызвавшее ошибку, запуск этой программы выводит,
Area calculation failed, radius -20.00 is less than zero
Используйте типы структур и поля для предоставления информации оerror
Больше информации о
Также можно использовать тип структуры, который реализует интерфейс ошибки какerror
. Это дает нам больше гибкости. В нашем примере, если мы хотим увидеть ошибки, единственный способ — разобратьArea calculation failed, radius -20.00 is less than zero
. Это неподходящий подход, потому что, если описание изменится, логика нашего кода должна быть изменена.
Мы будем использовать поля структуры для предоставленияerr
иradius
. Мы создадим реализациюerror
Структурный тип интерфейса и использует его поля для предоставления дополнительной информации о нем.
Первым шагом является создание типа структуры для представленияerror
. Соглашение об именах типовError
конец. Поэтому мы называем тип структуры какareaError
type areaError struct {
err string
radius float64
}
Вышеуказанный тип структуры имеет полеradius
, в котором хранитсяerror
значение радиуса , иerr
Поле хранит фактическое содержание ошибки.
Следующим шагом является реализацияerror
интерфейс.
func (e *areaError) Error() string {
return fmt.Sprintf("radius %0.2f: %s", e.radius, e.err)
}
В приведенном выше фрагменте кода мы используем приемник указателя.* areaError
реализует неправильный интерфейсError
метод. Этот метод печатаетradius
иerr
описывать.
Давай напишемmain
функция иcircleArea
функция завершения программы.
package main
import (
"fmt"
"math"
)
type areaError struct {
err string
radius float64
}
func (e *areaError) Error() string {
return fmt.Sprintf("radius %0.2f: %s", e.radius, e.err)
}
func circleArea(radius float64) (float64, error) {
if radius < 0 {
return 0, &areaError{"radius is negative", radius}
}
return math.Pi * radius * radius, nil
}
func main() {
radius := -20.0
area, err := circleArea(radius)
if err != nil {
if err, ok := err.(*areaError); ok {
fmt.Printf("Radius %0.2f is less than zero", err.radius)
return
}
fmt.Println(err)
return
}
fmt.Printf("Area of rectangle1 %0.2f", area)
}
В приведенной выше программе строка 17 изcircleArea
Используется для вычисления площади круга. Эта функция сначала проверяет, меньше ли радиус нуля, и, если да, использует радиус ошибки и соответствующее описание ошибки для созданияareaError
, затем вернуться на строку 19areaError
адрес и содержание ошибки. Поэтому мы предоставляем большеerror
информацию, в данном примере с использованиемerror
Поля структуры реализуют настройку.
Если радиус неотрицательный, эта функция вычисляет и возвращает сумму площадейnil
в строке 26main
В функции пытаемся вычислить площадь круга с радиусом -20. Будет возвращена ошибка, поскольку радиус меньше нуля.
Проверяем на строке 27err
Этоnil
, и утвердите в следующей строкеerr
да* areaError
тип. если* areaError类型
, используем в строке 29err.radius
вызватьerror
изradius
, затем распечатайте пользовательское содержимое ошибки и вернитесь из программы.
вывод,
Radius -20.00 is less than zero
Теперь воспользуемся второй стратегией, описанной в предыдущем руководстве, и воспользуемся подходом с пользовательским типом ошибки для предоставления информации оerror
Чтобы получить больше информации.
Метод использования структурного типа обеспечиваетerror
Больше информации о
В этом разделе мы напишем программу, которая вычисляет прямоугольную площадь. Программа выдаст ошибку, если длина или ширина меньше 0.
Первым шагом является создание представленияerror
Структура.
type areaError struct {
err string //error description
length float64 //length which caused the error
width float64 //width which caused the error
}
Приведенный выше тип структуры ошибки содержит поле описания ошибки.err
и длинаlength
и ширинаwidth
.
Теперь мы определилиerror
тип, давайте реализовыватьerror
интерфейс и добавьте несколько методов для типа, чтобы предоставить больше информации о нем.
func (e *areaError) Error() string {
return e.err
}
func (e *areaError) lengthNegative() bool {
return e.length < 0
}
func (e *areaError) widthNegative() bool {
return e.width < 0
}
В приведенном выше фрагменте кода мы начинаем сError
Метод возвращает описание ошибкиe.err
. когдаlength
Когда меньше 0,lengthNegative
метод возвращаетtrue
, и когдаwidth
Когда меньше 0,widthNegative
метод возвращаетtrue
. В данном случае эти два метода предоставляют информацию о том, произошел ли сбой вычисления площади из-за отрицательной длины или отрицательной ширины. Поэтому мы используемerror
методы типа структуры для предоставления дополнительной информации о файлах .
Следующим шагом является реализация функции вычисления площади.
func rectArea(length, width float64) (float64, error) {
err := ""
if length < 0 {
err += "length is less than zero"
}
if width < 0 {
if err == "" {
err = "width is less than zero"
} else {
err += ", width is less than zero"
}
}
if err != "" {
return 0, &areaError{err, length, width}
}
return length * width, nil
}
вышеrectArea
Функция проверяет, если длина или ширина меньше 0, а если да, возврат 0 иerror
, иначе возвращает площадь прямоугольника иnil
.
Давайте создадимmain
функция для завершения всей программы.
func main() {
length, width := -5.0, -9.0
area, err := rectArea(length, width)
if err != nil {
if err, ok := err.(*areaError); ok {
if err.lengthNegative() {
fmt.Printf("error: length %0.2f is less than zero\n", err.length)
}
if err.widthNegative() {
fmt.Printf("error: width %0.2f is less than zero\n", err.width)
}
return
}
fmt.Println(err)
return
}
fmt.Println("area of rect", area)
}
существуетmain
работает, проверяемerr
Этоnil
. если это неnil
, мы утверждаем в следующей строке* areaError
. затем используйтеlengthNegative
иwidthNegative
метод, который проверяет, вызвана ли ошибка отрицательной длиной или отрицательной шириной. Мы печатаем соответствующиеerror
содержание и возврат из программы. Поэтому мы используем метод типа структуры, чтобы предоставить больше информации о ней.
Если ошибок нет, область прямоугольника будет напечатана.
Наконец, полная программа размещена для справки.
package main
import "fmt"
type areaError struct {
err string //error description
length float64 //length which caused the error
width float64 //width which caused the error
}
func (e *areaError) Error() string {
return e.err
}
func (e *areaError) lengthNegative() bool {
return e.length < 0
}
func (e *areaError) widthNegative() bool {
return e.width < 0
}
func rectArea(length, width float64) (float64, error) {
err := ""
if length < 0 {
err += "length is less than zero"
}
if width < 0 {
if err == "" {
err = "width is less than zero"
} else {
err += ", width is less than zero"
}
}
if err != "" {
return 0, &areaError{err, length, width}
}
return length * width, nil
}
func main() {
length, width := -5.0, -9.0
area, err := rectArea(length, width)
if err != nil {
if err, ok := err.(*areaError); ok {
if err.lengthNegative() {
fmt.Printf("error: length %0.2f is less than zero\n", err.length)
}
if err.widthNegative() {
fmt.Printf("error: width %0.2f is less than zero\n", err.width)
}
return
}
}
fmt.Println("area of rect", area)
}
Run in playgroundвывод программы,
error: length -5.00 is less than zero
error: width -9.00 is less than zero
мы виделиerror
Работайте с примерами двух из трех методов, описанных в руководстве, чтобы получить больше информации о нем.
Третий способ проще – использовать метод прямого сравнения. Я оставлю это в качестве упражнения для вас, чтобы выяснить, как использовать эту стратегию для настройки нашихerror
Чтобы получить больше информации.