Comments 20
На самом деле, не по ссылке: There is no pass-by-reference in Go
Да! Странно, что автор статьи не исследовал вопрос, о котором решил писать.
Map — это структура, передается по значению. Собственно поэтому возможны вот такие вещи.
Map — это структура, передается по значению. Собственно поэтому возможны вот такие вещи.
Позволил себе переделать ваш пример. Со слайсами такие вещи тоже работают.
pfihr, map просто более сложная структура, чем slice. Если я правильно понимаю, map расширяется «бакетами», т.е. у него нет надобности копировать содержимое в новую память. Слайсу же необходима непрерывность, поэтому слайс расширяется выделением бОльшего блока и копированием старых данных в новый кусок памяти.
pfihr, map просто более сложная структура, чем slice. Если я правильно понимаю, map расширяется «бакетами», т.е. у него нет надобности копировать содержимое в новую память. Слайсу же необходима непрерывность, поэтому слайс расширяется выделением бОльшего блока и копированием старых данных в новый кусок памяти.
при этом, значения в этой структуре не меняются при изменении содержания и его реаллокации в памяти. В Вашем примере вы переопределяете переменную в рамках области видимости, это не связано со свойствами мапы.
В Вашем примере обычный шадоуинг: переопределена переменная внутри функции, поэтому переданный параметр остался неизменным. Исправленный пример. Map передается также, как и все другие структуры: указатель для простой передачи не нужен.
Maps, like channels, but unlike slices, are just pointers to runtime types. As you saw above, a map is just a pointer to a runtime.hmap structure.
Maps have the same pointer semantics as any other pointer value in a Go program. There is no magic save the rewriting of map syntax by the compiler into calls to functions in runtime/hmap.go.
Кстати, что map, chan не указатели, а структуры, содержащие в том числе указатели, указывает и то, что они создаются через make.
Dave Cheney с вами не согласен. Map все-таки указатель, в отличие от slice, хотя оба создаются с помощью make.
var m map[int]int
var s []int
var p uintptr
fmt.Println(unsafe.Sizeof(m), unsafe.Sizeof(s), unsafe.Sizeof(p)) // 8 24 8 (linux/amd64)
Если речь про uintptr, то да. Если же в чисто гошном смыле *map, то нет.
Думаю все же неверно говорить о том, что это указатель. Map не ведет себя как *map, пример я приводил выше. Если ему есть опровержение, то да — map это указатель.
Согласен с вами, если утверждение звучит как «map хранит uintptr значение, то есть с ним есть возможность работать, как с указателем в определенных условиях».
Думаю все же неверно говорить о том, что это указатель. Map не ведет себя как *map, пример я приводил выше. Если ему есть опровержение, то да — map это указатель.
Согласен с вами, если утверждение звучит как «map хранит uintptr значение, то есть с ним есть возможность работать, как с указателем в определенных условиях».
Там (по ссылке) объясняется почему так. В чисто гошном смысле *map в какой-то момент просто переименовали в map, п.ч. указатель, который не выглядит как указатель, смущает гораздо меньше, чем указатель, который нельзя разыменовать. Т.е. получить структуру мапа в переменную не получится, поэтому ваш пример не корректен. Например:
А должно? Вы в своем примере получаете параметром просто map, представьте на секунду, что это все-таки указатель, но получить его значение вы не можете. И? Толку от присваивания переменной с указателем make(map[...]..., 1). А к значению у вас доступа нет… вот и приходится «городить» указатель на указатель, чтобы менять исходное значение переданной переменной.
func someFunc(x *int) {
a := 5
x = &a
}
//...
b := 10
someFunc(b) // и что-то b не заменилось на 5
А должно? Вы в своем примере получаете параметром просто map, представьте на секунду, что это все-таки указатель, но получить его значение вы не можете. И? Толку от присваивания переменной с указателем make(map[...]..., 1). А к значению у вас доступа нет… вот и приходится «городить» указатель на указатель, чтобы менять исходное значение переданной переменной.
Более корректный прример относительно слов Дейва https://play.golang.org/p/aSEP5pd8LH
Если мы используем мапу и ее код гошки заменяет на разыменование, то код должен быть такой и тогда внутри функции мы можем сделать такое присваивание, однако поведение map отличается от такого, где есть разыменование.
Если мы используем мапу и ее код гошки заменяет на разыменование, то код должен быть такой и тогда внутри функции мы можем сделать такое присваивание, однако поведение map отличается от такого, где есть разыменование.
Заголовок вводит в заблуждение — в Go параметры передаются всегда по значению, т.е. копируются. Да, map — это указатель на структуру, но этот указатель один фиг передается копированием.
все верно, цель заметки была в том, чтобы показать, что изменение мапы в функции не равно изменению слайса
Передайте указатель на слайс и найдите 6 отличий.
Указатели и передача параметра по ссылке — это разные вещи. Например, в си вы можете передать параметр по ссылке, а можете (как в Go) передать по значению указатель на переменную. Передача параметра по ссылке нужна, когда вызываемая подпрограмма должна изменить переменную вызывающей подпрограммы. Грань довольно тонкая в сравнении с передачей указателя, я не могу придумать сходу кейс, где «по ссылке» действительно необходимо и нельзя обойтись передачей параметров по значению.
Может лучше озаглавить статью как-то так: «Тип map — ссылочный»?
Указатели и передача параметра по ссылке — это разные вещи. Например, в си вы можете передать параметр по ссылке, а можете (как в Go) передать по значению указатель на переменную. Передача параметра по ссылке нужна, когда вызываемая подпрограмма должна изменить переменную вызывающей подпрограммы. Грань довольно тонкая в сравнении с передачей указателя, я не могу придумать сходу кейс, где «по ссылке» действительно необходимо и нельзя обойтись передачей параметров по значению.
Может лучше озаглавить статью как-то так: «Тип map — ссылочный»?
Sign up to leave a comment.
Передача типа map в функцию