3 наиболее распространённых подводных камня в Go

2
5006
Добавить в избранное

Начиная изучение Go, многие сталкиваются с совершенно не очевидными моментами в этом языке. Рассмотрим три таких подводных камня в Go.


3 наиболее распространённых подводных камня в Go

1. Range

Начнем программирование на Go с основ. Функция range является одной из самых используемых в Go. Вот пример использования (не обращайте внимания, что мы присваиваем всем животным в зоопарке 999 ног):

Вышеприведённый код выглядит довольно невинно. Однако вы можете удивиться, узнав, что два fmt.Printf() выражения дают одинаковые результаты.

Подводный камень

Значения (хранятся как animal), по которым мы проходимся с помощью range, являются не указателями на значения, а копиями значений из zoo.

Решение

Чтобы изменить элемент массива, мы должны изменить этот элемент через указатель:

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

2. «…» и вариативные функции

Быть может, вы использовали “…” в ЯП С для создания вариативной функции; вариативная функция – это функция, принимающая переменное количество аргументов.

В C вы должны последовательно вызвать макрос va_arg для доступа к необязательным аргументам. И, если вы попытаетесь использовать вариативный аргумент любым другим способом, компилятор выдаст ошибку.

Программирование на Go задает несколько иные правила. В Golang это выглядит так же, как и в С, но работает по-другому. Здесь представлена вариативная функция myFprint. Обратите внимание, как используется вариативный аргумент a:

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

Подводный камень

В Go вариативные параметры разделяются компилятором.

Это означает, что вариативный аргумент a – на самом деле отдельная переменная. Поэтому приведённый ниже код действителен:

3. Слайсинг

Продолжим изучение Go слайсингом. Если вы делали слайсинг в Python, то наверняка помните, что этот приём даёт вам новый список со ссылками на элементы. Это свойство позволяет использовать такой Python код:

Если вы попробуете то же самое в Go, получите что-то другое:

Подводный камень

В Go слайс имеет тот же базовый массив и ёмкость, что и оригинал. В Golang если вы измените элемент в слайсе, исходное содержимое тоже будет изменено.

Решение

Если вы хотите получить независимый слайс, у вас есть два варианта:

И, согласно StackOverflow, append намного быстрее make.

Материалы по теме:

 

Интересуетесь алгоритмами?

Подпишитесь на нашу рассылку, чтобы получать больше интересных материалов:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




2 Комментарии

Оставьте комментарий