附加到切片的元素的地址

I want to create element, add it to the slice and change it by its address. I expect that the change of the element from the outside will change also a slice. But after the addition, a new slice is created. I use serialization, so the use of an slice of addresses is not suitable, also the addition of elements occurs in different goroutines, so accessing the last added element is also not suitable.

package main

import (
    "fmt"
)

func main() {
    var a []int
    b := 1
    fmt.Println("old addr:", &b)
    // old addr: 0x10414020
    a = append(a, b)
    fmt.Println("new addr:", &a[0])
    // new addr: 0x10414028
}

play golang example

This is not an issue of append() creating a new slice header and backing array.

This is an issue of you appending b to the slice a, a copy of the value of the b variable will be appended. You append a value, not a variable! And by the way, appending (or assigning) makes a copy of the value being appended (or assigned).

Note that the address of b and a[0] will also be different if you do not call append() but instead preallocate the slice and simply assign b to a[0]:

var a = make([]int, 1)
b := 1
fmt.Println("old addr:", &b)
// old addr: 0x10414024
a[0] = b
fmt.Println("new addr:", &a[0])
// new addr: 0x10414020

Try it on the Go Playground.

The reason for this is because the variable b and a are distinct variables; or more precisely the variable b and a's backing array reserving the memory for its elements (including the memory space for a[0]), so their addresses cannot be the same!

You cannot create a variable placed to the same memory location of another variable. To achieve this "effect", you have pointers at your hand. You have to create a pointer variable, which you can set to point to another, existing variable. And by accessing and modifying the pointed value, effectively you are accessing and modifying the variable whose address you stored in the pointer.

If you want to store "something" in the a slice through which you can access and modify the "outsider" b variable, the easiest is to store its address, which will be of type *int.

Example:

var a []*int
b := 1
fmt.Println("b's addr:", &b)
a = append(a, &b)
fmt.Println("addr in a[0]:", a[0])

// Modify b via a[0]:
*a[0] = *a[0] + 1
fmt.Println("b:", b)

Output (try it on the Go Playground):

b's addr: 0x10414020
addr in a[0]: 0x10414020
b: 2

Quoted program behaves perfectly correct - addresses denote storage locations, b int is one such location and element inside the slice is other one.

You most probably need to store pointers not ints.

Now with regard to serialization - I am not sure what kind do you have in mind, but in general you could proceed like below:

type myArray []*int
var a myArray
//...

func (x myArray) Serialize() []byte { .... }

Where Serialize satisfies the interface used by your serializator.

Assigning values always lets the runtime allocate new memory for the copied value and that allocated memory will have another address. If you append to a slice of values, you will always copy the variable.

If you have to access the elements from different go routines, you will have to make it thread safe. You have to do that, whether you are using values or references.