Pull to refresh

Comments 7

Вот блин: на захвате переменной цикла споткнулся. И вроде ж известная грабля, сам при написании уже на автомате отслеживаю. А при чтении чужого кода не заметил :-(

Задача 1

Компилятор будет молчать. Это корректный код. Жаловаться может только линтер, который при компиляции сам по себе не выполняется, а тот же golangci-lint у меня на такой код не жалуется. Ну и в ответе опечатка - 42, а не 43

Задача 2

Плохой практикой скорее будет объявлять подобные блоки, но variable shadowing плохой практикой не является. Это повсеместная практика например для переменных ошибок. Чрезвычайно редко, когда я сталкивался с багами из-за этого. А на практике будет релевантен код с замыканием. Кстати ниодин линтер у меня на это не жалуется, в том числе go vet. Там этой проверки нет, судя по коду.

Задача 5

Слайсы это не ссылочный тип. Именно по этой причине в первой задаче получается такой ответ. Слайсы это value тип. При присвоении другой переменной содержимое копируется. Тот факт, что он внутри себя содержит указатель на массив, не делает его ссылочным. Ссылочный тип это канал или map, например.

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

Задача 1

Вы правы, замечание сделает не компилятор, а линтер, а если конкретнее, ineffassign, который отслеживает бесполезные присваивания. Странно, что у вас golangci-lint не жалуется, ибо упомянутый линтер входит в него. Возможно, дело в настройках или версии.

Задача 2

Я не утверждала, что variable shadowing - плохая практика. Лишь заметила, что в Go она таковой считается. Об этом говорит хотя бы то, что core team языка разработала линтер для этого.

Он не входит в поставку go vet по умолчанию, а оформлен в виде отдельного инструмента, который можно установить дополнительно и подключить к go vet. Об этом написано непосредственно в справке этой утилиты: go help vet:

For example, the 'shadow' analyzer can be built and run using these commands:

   go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
   go vet -vettool=$(which shadow)

Задача 5

Это терминологический спор. Можно ли считать ссылочным тип, при копировании значения которого связанные данные не копируются? Я считаю, что да.

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

К слову, реализации ссылочных типов как раз и работают на базе указателя на данные. Так что это вполне аргумент за.

Не терминологический, это по факту так. Слайс это структура из трех полей - указатель на начало массива, длина, capacity. Все три этих поля копируются. Если бы слайс был ссылочным типом, то они все передавались бы по ссылке и в вашем первом примере мы получили бы совсем другой ответ, но это не так. Это прямо противоречит тезису "если менять конкретный элемент через одну переменную, значение этого элемента изменится во всех местах, где есть копия этой ссылки". Нет, не изменится. Только если повезет и внутри слайса будет указатель на одну и туже область памяти, чего мы знать не можем без unsafe. Об этом постоянно говорят новичкам и объясняют разработчики языка. В Go все передается по значению (да, даже ссылочные типы. В их случае по значению передается указатель) и нужно понимать семантику типов. После этого все вопросы отпадут сами собой и ответы на первую и пятую задачи будут очевидны.

Ближайший аналог слайсов это Span в C#, который имеет примерно такую же семантику и тоже value-тип. Наличие внутри него указателя точно так же не делает его ссылочным. В C# даже специальный синтаксис придумали, чтобы гарантировать это - ref struct.

Проблема с variable shadowing - это просто "упрощения" языка, а конкретно что можно объявить и инициализировать переменную без ключевого слова. И я бы сказал что такое "упрощение" пошло не на пользу языку.

Практически во всех языках новый блок - это новый scope, и соответственно, если в блоке переменная без ключевого слова то обращаемся к переменной что объявлена в outer scope.

Решил три, но я не знаю go. Прям непонятно что отвечать.

В задаче №3 ответы 1 и 2 не могут быть правильными в любом случае.
Sign up to leave a comment.

Articles