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

Для чего нужен указатель структуры в слайсе?

Привет. Есть пример:
type Player struct {
    Id      int64
    Name    string
}
var players[] *Player
var players2[] Player
func main() {
    players = append(players, &Player{Id: 1, Name: "Bob"})
    players2 = append(players2, Player{Id: 1, Name: "Bob"})
    fmt.Println(players)
    fmt.Println(players2)
//...
}


В первом слайсе (players) у нас хранятся ссылки на структуры, во втором (players2) сами структуры. При изменении значений в цикле (присваиваем новый Name, например), и при выводе этих слайсов, результаты идентичны: везде значения поменяются.

В каких случаях нужно писать var players[] *Player, а в каких - var players2[] Player ?
  • Вопрос задан
  • 186 просмотров
Подписаться 1 Простой 2 комментария
Решения вопроса 1
EvgenyMamonov
@EvgenyMamonov Куратор тега Go
Senior software developer, system architect
Тут сильно зависит от того, как вы будете использовать данные.

Например, если вы во все функции передаёте players
someFunc1(players)
someFunc2(players)
someFunc3(players)

тогда указатели на конкретного player'a использовать особо смысла нет, от этого будет даже хуже, т.к. при создании нового player'a (при взятии адреса) будет задействован сборщик мусора, что вызовет бесполезную доп. нагрузку.

Если же player структура не маленькая или их очень много, и обработка будет происходить каждого player'a в отдельности + при этом будет использоваться много разных функций, например вот так
func main() {
    var players[] *Player
    players = append(players, &Player{Id: 1, Name: "Bob"})
    ...
    players = append(players, &Player{Id: 100, Name: "Bob"})
    for i := range players {
        someFunc1(players[i])
        someFunc2(players[i])
        someFunc3(players[i])
        someFunc4(players[i])
        // или одна из someFunc вызывает еще какие то функции и передаёт players туда 
    }
}

в этом случае вы получите выигрыш в производительности за счёт того, что при вызове каждой функции будет копироваться лишь указатель (8байт на 64битных процессорах) вместо всей структуры
Если точнее - вы получите доп. нагрузку за счёт того, что будет задействован сборщик мусора, но за счёт того, что вместо большого объёма данных при каждом вызове функции будет копироваться лишь указатель - вы получите выигрыш, который нивелирует проигрыш от сборщика мусора.

На всякий случай о том, когда есть смысл использовать указатель, а когда нет
https://qna.habr.com/q/1046708#answer_2019152
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Spargwy
20 годиков. Голанг баккенд девелопер
Указатель - тип данных, который показывает, где хранится объект в памяти.
Если ты передаёшь структуру функции, а не указатель на неё(для примера возьмём Player), то по факту создаётся копия этой структуры.
Если же ты передашь адрес структуры(&Player) в функцию, то те изменения, которые происходят в функции, будут изменять тот объект, который изначально передавался.

func EditPlayer(p Player) { 
    p.Name = "John"
}

func EditOriginalPlayer(p *Player) {
    p.Name = "John"
}

func main() {
    player := Player{Name: "Bob"}
    EditPlayer(player)
    fmt.Print(player.Name)//"Bob" Имя не изменяется т.к. передаётся копия
    EditOriginalPlayer(&player)
    fmt.Print(player.Name)//"John" Имя изменилось т.к. передаётся адрес структуры т.е. "оригинал"
}
Ответ написан
Ваш ответ на вопрос

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

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