Основное Преимущество Го

Если вы спросите среднестатистического разработчика Go, какие преимущества имеет Go, вы, скорее всего, услышите знакомый список преимуществ.

О них уже много написано, но очень часто игнорируется другая вещь, гораздо более интересная — долгосрочный эффект тех или иных решений по дизайну языка.

Хочу еще немного расширить эту тему, которая на самом деле актуальна не только для Go. Но в этой статье я возьму в качестве примера два аспекта — систему обработки ошибок и тестирования Go — и попытаюсь показать, как конструкция языка заставляет людей писать более качественный код.

Основное преимущество Го



Обработка ошибок

Вы наверняка знаете, что в императивных языках есть два основных механизма сообщения об ошибке — выдача исключения или явный возврат кода/значения.

Можно сказать, что здесь даже два лагеря — сторонники исключений и сторонники явного возврата, но всё несколько хуже.

На самом деле есть два лагеря, но они разные — те, кто понимает важность обработки ошибок в коде, и те, кто по большей части игнорирует этот аспект программирования.

При этом второй лагерь пока является безусловным лидером.

Логично предположить, что именно это отличает «хороших» программистов от «плохих», и доля истины здесь, несомненно, есть.

Но есть одна вещь.

Инструментарий — в данном случае «язык программирования» — тоже имеет значение.

Если с вашим языком гораздо легче поступать «неправильно», чем «правильно» — будьте уверены, никакие статьи и книги «Как не писать на [LANG]» не помогут — люди будут продолжать делать это неправильно.

Просто потому, что это проще.

Казалось бы, каждый школьник уже знает, что «глобальные переменные» — это зло.

На эту тему столько статей - вроде бы всем все понятно.

Но тем не менее — даже сейчас, в 2015 году, вы встретите тонны кода, использующего глобальные переменные.

Почему? А потому, что создание глобальной переменной — «сделать не так» практически в любом языке программирования занимает ровно одну строку.

При этом для создания любого «правильного варианта», любой минимальной обертки нужно потратить больше времени и сил.

Даже если на 1 символ больше, это имеет значение.

Это очень важно понимать: инструменты имеют значение.

Инструменты формируют наш выбор.

Но вернемся к обработке ошибок и попытаемся понять, почему авторы Go посчитали исключения «неправильным» и решили не реализовывать их в Go, и в чем разница между «возвратом нескольких значений» в Go и аналогичными в других языках.

В качестве примера возьмем простую вещь — открытие файла.

Вот код на C++

  
  
  
  
   

ifstream file; file.open ("test.txt");

Это полностью рабочий код, и «правильный» способ справиться с ошибкой — либо проверить флаг Failbit, либо включить ifstream.Exceptions() и обернуть все в блок try{} catch{}.

Но гораздо проще сделать «неправильно» — всего одна строчка, а «обработку ошибок можно добавить позже».

Тот же код в 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

Вместе с данным постом часто просматривают: