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

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

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

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

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

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

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

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

Решение

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

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

proglib.io

Добавить комментарий

Ваш e-mail не будет опубликован.

3 × 5 =