Обращение к полям структуры
"И снова эти указатели". Пример из курса. Автор обращается к *Воркеру и итерирует по списку юзеров, а не к разыменованному указателю (вроде так можно, ок, допускаем). Вопроса два:
- на строчке 37 берем одного юзера, и уже тут разыменовываем указатель. Не понятно, почему на 36стр. не разыменовываем, тут разыменовываем
- на строчке 37, если навести курсор, показывает тип *Юзер, хотя в структуре Воркер массив просто юзеров. Возможно сам отвечу на 1 и 2ой вопросы: возможно эти строчки идентичны, и указатель относится не к w?
&w.users[i]
&(w.users[i])
Ответы (2 шт):
На 36 строке мы бежим по индексам слайса. На 37-й получаем по индексу структуру юзера и присваиваем переменной user указатель на юзера. Мы не разыменовываем ничего на 37-й. Разыменование это когда мы перед переменной с указателем пишем *. А & это наоборот, получение адреса в памяти у значения, т.е. получение указателя.
В спецификации языка Го есть понятие адресуемости, addressability: https://go.dev/ref/spec#Address_operators
Оператор & возвращает адрес адресуемого операнда:
- переменная,
&v - разыменование указателя,
&*ptr - индексирование слайса,
&someSlice[i] - поле адресуемого операнда структурного типа,
&some.Field - индексирование адресуемого операнда типа массив,
&some.ArrField[i].
Кроме того, можно получить адрес у составного литерала, &SomeStruct{ SomeField: someVal }
В вашем случае &w.users[i] операндом является w.users[i]. w - переменная, значит адресумый операнд. w.users - поле адресумого операнда, тоже адресуемый операнд. Дальше наступает скользкий момент. В спецификации сказано про слайсы на одном уровне с переменными, зато про массивы сказано индексирование адресуемого массива. Тип []User - не массив, а слайс, но можно сделать вид, будто мы этого не понимаем, и обобщить спецификацию: w.users[i] - это индексирование адресуемого операнда типа слайс, и поэтому тоже адресуемый операнд. Я не первый раз сталкиваюсь с неполнотой спецификации, и поэтому не дёргаюсь )
Следовательно, выражение &w.users[i] есть получение адреса i-го элемента слайса w.users.
Ну и для примера несколько видов неадресуемых операндов:
- возвращаемое значение функции,
&f(x) - индексирование отображения,
var someMap = map[string]int{"one": 1} var ptr = &someMap[""] - константа
const x int = 0 var p = &x
