Если вы спросите среднестатистического разработчика Go, какие преимущества имеет Go, вы, скорее всего, услышите знакомый список преимуществ.
О них уже много написано, но очень часто игнорируется другая вещь, гораздо более интересная — долгосрочный эффект тех или иных решений по дизайну языка.
Хочу еще немного расширить эту тему, которая на самом деле актуальна не только для Go. Но в этой статье я возьму в качестве примера два аспекта — систему обработки ошибок и тестирования Go — и попытаюсь показать, как конструкция языка заставляет людей писать более качественный код.
Обработка ошибок
Вы наверняка знаете, что в императивных языках есть два основных механизма сообщения об ошибке — выдача исключения или явный возврат кода/значения.Можно сказать, что здесь даже два лагеря — сторонники исключений и сторонники явного возврата, но всё несколько хуже.
На самом деле есть два лагеря, но они разные — те, кто понимает важность обработки ошибок в коде, и те, кто по большей части игнорирует этот аспект программирования.
При этом второй лагерь пока является безусловным лидером.
Логично предположить, что именно это отличает «хороших» программистов от «плохих», и доля истины здесь, несомненно, есть.
Но есть одна вещь.
Инструментарий — в данном случае «язык программирования» — тоже имеет значение.
Если с вашим языком гораздо легче поступать «неправильно», чем «правильно» — будьте уверены, никакие статьи и книги «Как не писать на [LANG]» не помогут — люди будут продолжать делать это неправильно.
Просто потому, что это проще.
Казалось бы, каждый школьник уже знает, что «глобальные переменные» — это зло.
На эту тему столько статей - вроде бы всем все понятно.
Но тем не менее — даже сейчас, в 2015 году, вы встретите тонны кода, использующего глобальные переменные.
Почему? А потому, что создание глобальной переменной — «сделать не так» практически в любом языке программирования занимает ровно одну строку.
При этом для создания любого «правильного варианта», любой минимальной обертки нужно потратить больше времени и сил.
Даже если на 1 символ больше, это имеет значение.
Это очень важно понимать: инструменты имеют значение.
Инструменты формируют наш выбор.
Но вернемся к обработке ошибок и попытаемся понять, почему авторы Go посчитали исключения «неправильным» и решили не реализовывать их в Go, и в чем разница между «возвратом нескольких значений» в Go и аналогичными в других языках.
В качестве примера возьмем простую вещь — открытие файла.
Вот код на C++
Это полностью рабочий код, и «правильный» способ справиться с ошибкой — либо проверить флаг Failbit, либо включить ifstream.Exceptions() и обернуть все в блок try{} catch{}.ifstream file; file.open ("test.txt");
Но гораздо проще сделать «неправильно» — всего одна строчка, а «обработку ошибок можно добавить позже».
Тот же код в Python: file = open('test.txt', 'r')
То же самое — гораздо проще просто вызвать open() и заняться обработкой ошибок позже.
При этом «обработка ошибок» чаще всего означает «завернуть в try-catch, чтобы не вылетало».
(Сразу оговорюсь - этот пример не пытается сказать, что в C++ или Python программисты не проверяют ошибки при открытии файла - в этом примере из учебника они, скорее всего, проверяют чаще всего.
Но в менее «стандартный» код, смысл этого примера становится более очевидным.
)
Вот аналогичный пример в Go: file, err := os.Open("test.txt")
И вот тут становится интересно — мы не можем просто получить обработчик файла, «забыв» о возможной ошибке.
Переменная типа error возвращается явно, и ее нельзя просто игнорировать — неиспользуемые переменные являются ошибкой времени компиляции в Go: .
/main.go:8: err declared and not used
Нужно либо подавить ее, заменив на _, либо как-то проверить ошибку и отреагировать, например: if err != nil {
Теги: #golang #обработка ошибок #тестирование #тестирование ИТ-систем #программирование #Go
-
Что Такое Рекордер Youtube?
19 Oct, 24 -
Рёмер, Оле Кристенсен
19 Oct, 24 -
Эээээ
19 Oct, 24 -
Использование Библиотеки Подкачки С Realm
19 Oct, 24