Мне кажется, что альтернативы Google для исключений
- GO: возврат нескольких значений "return val, err;"
- GO, C ++: нулевые проверки (досрочный возврат)
- GO, C ++: "обработать чертову ошибку" (мой термин)
C ++: утверждение (выражение)
GO: отсрочка / паника / восстановление - языковые функции, добавленные после того, как был задан этот вопрос
Достаточно ли полезен возврат нескольких значений, чтобы выступать в качестве альтернативы? Почему «утверждения» считаются альтернативами? Google думает, что это О.К. если программа останавливается, если возникает ошибка, которая не обрабатывается правильно?
Эффективный GO: множественные возвращаемые значения
Одной из необычных особенностей Go является то, что функции и методы могут возвращать несколько значений. Это может быть использовано для улучшения пары неуклюжих идиом в программах на C: возврат ошибок внутри полосы (например, -1 для EOF) и изменение аргумента.
В C ошибка записи сигнализируется
отрицательный счет с кодом ошибки
секрет в прочном месте.
В Go, Write может вернуть счетчик и
ошибка: «Да, вы написали несколько байтов, но
не все из них, потому что вы заполнили
устройство». Подпись * File.Write
В комплектацию входит:
func (file *File) Write(b []byte) (n int, err Error)
и как говорится в документации
возвращает количество записанных байтов
и не ноль Ошибка, когда n! = len (b).
Это общий стиль; увидеть
раздел об обработке ошибок для более
примеры.
EO GO: Именованные параметры результата
Возвращаемые или возвращаемые "параметры"
Функция Go может иметь имена и
используется как обычные переменные, так же, как
входящие параметры. Когда названо,
они инициализируются в ноль
значения для их типов, когда
функция начинается; если функция
выполняет оператор возврата без
аргументы, текущие значения
Параметры результата используются в качестве
возвращаемые значения.
Имена не обязательны, но они
может сделать код короче и понятнее:
это документация Если мы назовем
результаты следующего становится очевидным
который возвратил int is which.
func nextInt(b []byte, pos int) (value, nextPos int) {
Поскольку именованные результаты инициализируются и привязываются к
возвращение без прикрас, они могут упростить как
ну как уточнить. Вот версия
io.ReadFull, который использует их хорошо:
func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
for len(buf) > 0 && err == nil {
var nr int;
nr, err = r.Read(buf);
n += nr;
buf = buf[nr:len(buf)];
}
return;
}
Почему в Go нет исключений?
Исключения - похожая история. Был предложен ряд конструкций для исключений, но каждый добавляет значительную сложность к языку и времени выполнения. По самой своей природе исключения охватывают функции и, возможно, даже функции; они имеют широкие последствия. Существует также обеспокоенность по поводу того, какое влияние они окажут на библиотеки. По определению, они являются исключительными, но опыт работы с другими языками, которые их поддерживают, показывают, что они сильно влияют на спецификации библиотек и интерфейсов. Было бы неплохо найти дизайн, который позволил бы им быть по-настоящему исключительными, не поощряя общие ошибки превращаться в особый поток управления, который требует от каждого программиста компенсация.
Как и дженерики, исключения остаются открытым вопросом.
Руководство по стилю Google C ++: исключения
Решение:
На их лице польза от использования
исключения перевешивают затраты,
особенно в новых проектах. Тем не мение,
для существующего кода, введение
исключения имеют последствия для всех
зависимый код. Если исключения могут быть
распространяется за пределы нового проекта, это
также становится проблематичным для интеграции
новый проект в существующий
Код без исключений. Потому что большинство
существующий код C ++ в Google не
готовы иметь дело с исключениями, это
сравнительно сложно принять
новый код, генерирующий исключения.
Учитывая, что существующий код Google
нетt исключительная терпимость, затраты на
используя исключения несколько больше
чем затраты в новом проекте.
Процесс преобразования будет медленным
и подвержен ошибкам. Мы не верим в это
доступные альтернативы
исключения, такие как коды ошибок и
утверждения, ввести существенное
бремя.
Наш совет против использования исключений:
не основаны на философских или
моральные основания, но практические.
Потому что мы хотели бы использовать наш
проекты с открытым исходным кодом в Google и
это трудно сделать, если те
проекты используют исключения, нам нужно
советую от исключений в гугле
проекты с открытым исходным кодом, а также. вещи
было бы иначе, если бы мы имели
сделать все заново с нуля.
GO: отсрочка, паника и восстановление
Операторы отсрочки позволяют нам думать о закрытии каждого файла сразу после его открытия, гарантируя, что независимо от количества операторов возврата в функции, файлы будут закрыты.
Поведение отложенных операторов является простым и предсказуемым. Есть три простых правила:
1. Аргументы отложенной функции оцениваются при оценке оператора defer.
В этом примере выражение "i" вычисляется при отсрочке вызова Println. Отложенный вызов выведет «0» после возврата функции.
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
2. Отложенные вызовы функций выполняются в порядке «последний пришел - первый вышел» после возврата окружающей функции. Эта функция выводит «3210»:
func b() {
for i := 0; i < 4; i++ {
defer fmt.Print(i)
}
}
3. Отложенные функции могут считывать и присваивать именованным возвращаемым значениям возвращаемой функции.
В этом примере отложенная функция увеличивает возвращаемое значение i после возврата окружающей функции. Таким образом, эта функция возвращает 2:
func c() (i int) {
defer func() { i++ }()
return 1
}
Это удобно для изменения значения ошибки, возвращаемого функцией; мы скоро увидим пример этого.
Паника - это встроенная функция, которая останавливает обычный поток управления и начинает паниковать. Когда функция F вызывает панику, выполнение F останавливается, все отложенные функции в F выполняются нормально, а затем F возвращается к своему абоненту. Для вызывающего абонента F ведет себя как призыв к панике. Процесс продолжается вверх по стеку до тех пор, пока не будут возвращены все функции в текущей процедуре, после чего программа вылетает. Панику можно инициировать, вызывая панику напрямую. Они также могут быть вызваны ошибками во время выполнения, такими как доступ к массиву за пределами допустимого диапазона.
Восстановление - это встроенная функция, которая восстанавливает контроль над программой, вызывающей панику. Восстановление полезно только в отложенных функциях. Во время обычного выполнения вызов для восстановления вернет ноль и не будет иметь никакого другого эффекта. Если текущая процедура вызывает панику, вызов restore захватит значение, данное панике, и возобновит нормальное выполнение .
Вот пример программы, которая демонстрирует механику паники и отсрочки:
<snip>
Реальный пример паники и восстановления см. В пакете json из стандартной библиотеки Go. Он декодирует JSON-кодированные данные с помощью набора рекурсивных функций. Когда встречается искаженный JSON, парсер вызывает панику, чтобы размотать стек для вызова функции верхнего уровня, который восстанавливается после паники и возвращает соответствующее значение ошибки (см. Функции «error» и «unmarshal» в decode.go) , Подобный пример этой техники есть в подпрограмме Compile пакета regexp. Соглашение в библиотеках Go заключается в том, что даже когда пакет использует внутреннюю панику, его внешний API все еще предоставляет явные возвращаемые значения ошибок.
Другие варианты использования defer (кроме файла. Пример закрытия (), приведенный ранее) включает освобождение мьютекса:
mu.Lock()
defer mu.Unlock