Golang в настоящее время имеет версию 1.17 (январь 2022 г.). Несмотря на то, что неясно, когда будет выпущен Golang 2.0 и какие функции он включает, есть несколько интересных черновиков, и весьма вероятно, что по крайней мере некоторые из этих черновиков будут частью Golang 2.0. В этой серии я подытожу основные функции Golang 2.0, и мы начнем с обработки ошибок.
Обработка ошибок
Обработка ошибок в Golang — одна из самых обсуждаемых тем. Прямо сейчас Golang заставляет вас — и это хорошо — проверять ошибку после вызова любой функции, которая дает результат в письменной форме.
if (err != nil) { return err // or do something else }
По моему честному мнению, это хорошо, что в Golang есть такая явная проверка ошибок, поскольку она дает вам знать об обработке ошибок. Однако это также приводит к написанию одного и того же кода снова и снова, что не идеально.
В проекте Golang 2.0 об этом позаботились, введя новые ключевые слова check
и handler
функции. Вместо того, чтобы явно проверять каждую ошибку, вы добавляете ключевое слово check
перед функцией, чтобы указать, что эти возвращаемые значения должны быть проверены с помощью функции-обработчика. Небольшой пример будет выглядеть так
func foobar(a, b int) error { handle err { return err } // This is our handler x := check foo(a, b) // check invokes the handle func y := check bar(a, b) // this on as well if (x > y) { return fmt.Errorf("This is an error") } }
Давайте пройдемся по этому построчно. Сначала мы определяем нашу функцию foobar, которая принимает a и b в качестве входных данных и возвращает ошибку. В следующей строке мы определяем нашу функцию обработки ошибок, обозначенную ключевым словом handle
. Функция-обработчик принимает аргумент типа error и имеет ту же сигнатуру возврата, что и объемлющая функция. Таким образом, когда foobar возвращает только ошибку, обработчик может вернуть только ошибку. Если foobar вернет (int, error)
, функция обработчика должна будет вернуть, например. 0,err
.
Ключевое слово check
указывает, что эту функцию следует проверять с помощью предопределенной функции обработки ошибок. Поэтому вместо того, чтобы писать
x, err := foo(a, b)
if (err != nil) {
return err
}
мы пишем только x := check foo(a, b)
. Это выполняет тот же поток кода, но не создает никаких дополнительных затрат кода.
Одна приятная особенность обработчиков заключается в том, что вы можете создавать цепочки обработчиков. Давайте посмотрим на следующий код.
func foobar(a, b int) error { handle err { return err } // This is our handler x := check foo(a, b) // check invokes the first handle func y := check bar(a, b) // this on as well if (x > y) { handle err { err = fmt.Errorf("doSomething with %x and %y, x, y) } // second handler check doSomething(x, y) // invokes second handler and then the first } check doSomething(y, x) // invokes first handler return nil }
Как видно из приведенного выше кода, если мы определим несколько функций-обработчиков, они будут выполняться в обратном порядке. Будьте осторожны, функции-обработчики действительны только для области, в которой они определены. Таким образом, функция-обработчик, определенная в блоке if
, будет вызываться только в пределах области.
Предложение по обработке ошибок выглядит многообещающе. Несмотря на то, что сейчас мне нравится явная обработка ошибок в Golang, приятно, что мы можем сократить накладные расходы на код, особенно в больших проектах. Я все еще не уверен, приведет ли это к большей сложности, чем к удобочитаемости, но я с нетерпением жду возможности протестировать это.
Если вас интересуют другие статьи о Golang, ознакомьтесь со следующими статьями.
https://itnext.io/the-power-of-golang-keyword-defer-b31bdecf10b6
Ресурсы
https://go.googlesource.com/proposal/+/master/design/go2draft.md