Задать вопрос
@worldhellok

Как понять когда ставить указатель?

Добрый день! Подскажите пожалуйста, заметил что в golang очень часто используюется * вроде бы называется указатель, так вот как понять когда ставить эту звездочку * ?
  • Вопрос задан
  • 633 просмотра
Подписаться 3 Простой Комментировать
Решения вопроса 1
EvgenyMamonov
@EvgenyMamonov Куратор тега Go
Senior software developer, system architect
Указатель, по сути, хранит адрес каких то данных (переменной, структуры, слайса и т.д.).
Иными словами он "указывает" на область данных.

Чтобы понять как им пользоваться - сначала нужно понять для чего он вообще используется.
Представьте что у вас есть структура, которая содержит много разных полей, в которых содержится большой объём данных.

Например:
type BigStruct struct {
    field1 int
    filed2 string
    field3 uint
    field4 []byte
    ...
    field50 string
}

Предположим, что после создания этой структуры и заполнения всех её полей она занимает в памяти 300мб.

Если вы сделаете функцию, которая будет принимать такую структуру как агрумент, например вот так
func Report(s BigStruct)
то при каждом вызове этой функции вся структура (300мб) каждый раз будут копироваться.
Пример:
s := BigStruct{}
// заполняем поля
Report(s)


Чтобы избежать такой мега нагрузки - можно передавать не копию данных, а указатель, т.е. адрес в памяти, где хранится сама структура.
Для этого нужно объявить агрумент функции как указатель, т.е. ставим *.
func Report(s *BigStruct)
А код уже будет выглядеть вот так.
s := BigStruct{}
// заполняем поля
Report(&s) // тут добавился & - берём адрес структуры, а не саму структуру

Или второй вариант
// создаём переменную s сразу с типом указатель на BigStruct
s := &BigStruct{}
// заполняем поля
Report(s) // поскольку s уже является указателем - & тут не нужен


В общем * используется:
- когда нужно объявить переменную
var s *BigStruct
- когда нужно прочитать/записать значение, которое храниться по адресу указателя
var i *int
    i = new(int)
    *i = 10 // пишем значение

    fmt.Printf("i: %v\n", i)
    fmt.Printf("*i: %v\n", *i)

Вывод будет примерно таким
i: 0xc0000160d8 (это адрес памяти, где лежит значение переменной i)
*i: 10 (а это её значение)


& (амперсанд) используется когда нужно получить адрес переменный.

Еще один вариант применения - если нужно иметь возможность модифицировать данные у параметра функции. Если нужны примеры - дайте знать, я напишу.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
samodum
@samodum
Какой вопрос - такой и ответ
По мере необходимости.
Рекомендую почитать сначала теорию о том что такое указатели, переменные, типы и структуры данных.
Без базовых понятий ты далеко не уедешь
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы