D
D
Dmitry2022-02-01 11:11:58
go
Dmitry, 2022-02-01 11:11:58

Why do we need a structure pointer in a slice?

Hello. There is an example:

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)
//...
}


In the first slice (players) we store links to structures, in the second (players2) the structures themselves. When changing values ​​in a cycle (we assign a new Name, for example), and when these slices are displayed, the results are identical: values ​​will change everywhere.

When should you write var players[] *Player and when should you write var players2[] Player ?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
E
Evgeny Mamonov, 2022-02-01
@dmitrydeco

It really depends on how you will use the data.
For example, if you pass players to all functions

someFunc1(players)
someFunc2(players)
someFunc3(players)

then it makes no sense to use pointers to a specific player, this will make it even worse, because when creating a new player'a (when taking the address), the garbage collector will be involved, which will cause a useless add. load.
If the player structure is not small or there are a lot of them, and processing will occur for each player individually + many different functions will be used, for example, like this
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 туда 
    }
}

in this case, you will get a performance gain due to the fact that when each function is called, only the pointer will be copied (8 bytes on 64-bit processors) instead of the entire structure
. load due to the fact that the garbage collector will be involved, but due to the fact that instead of a large amount of data, only a pointer will be copied with each function call, you will get a gain that offsets the loss from the garbage collector.
Just in case, when it makes sense to use a pointer, and when not
https://qna.habr.com/q/1046708#answer_2019152

D
Dmitry, 2022-02-01
@Spargwy

A pointer is a data type that indicates where an object is stored in memory.
If you pass a structure to a function rather than a pointer to it (let's take Player as an example), then in fact a copy of this structure is created.
If you pass the address of the structure (&Player) to the function, then the changes that occur in the function will change the object that was originally passed.

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" Имя изменилось т.к. передаётся адрес структуры т.е. "оригинал"
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question