Pointers keep changing

I am new to Golang and im trying to learn it by additionaly making a snake game clone. And whilst debuging I have noticed something weird.

The snake struct has a body []raylib.Vector2 (a raylib.Vector2 is just a struct that holds an x and y value) a head *raylib.Vector2 and a tail *raylib.Vector2 it also has a game context (game_ctx *Game) . Game is the main struct that coordinates everything. The thing that i have noticed is that whilst the head and tail pointer keep changing address values without being reassigned, the game_ctx has a stable address.

I thought that maybe the changing addresses is just how golang works, but when I saw that the game_ctx address doesn’t change I was starting to beleive that I am doint something wrong!

The problem function I think is the following :

func (this *Snake) draw() {
	for _, body_part := range this.body {
		color := rl.Black
		log.Debug("body_part: %p, tail: %p, head: %p", &body_part, this.tail, this.head)
		if &body_part == this.tail {
			color.R += 0xFF
		}
		if &body_part == this.head {
			color.B += 0xFF
		}

		if color == rl.Black {
			color = this.color
		}

		this.game_ctx.grid.drawCell(int(body_part.X), int(body_part.Y), color)

	}
}

with output (some extra output come from outside this function):

🟩 | DEBUG | 23-10-2024 22:27:48:715 | Body: 0xc000132c00
🟩 | DEBUG | 23-10-2024 22:27:48:732 | body_part: 0xc000015578, tail: 0xc0001c0400, head: 0xc0001c0410
🟩 | DEBUG | 23-10-2024 22:27:48:732 | body_part: 0xc000015588, tail: 0xc0001c0400, head: 0xc0001c0410
🟩 | DEBUG | 23-10-2024 22:27:48:732 | body_part: 0xc000015598, tail: 0xc0001c0400, head: 0xc0001c0410
🟩 | DEBUG | 23-10-2024 22:27:48:732 | Snake: &{game_ctx:0xc00009e0c0 body:[{X:0 Y:0} {X:0 Y:1} {X:1 Y:1}] head:0xc0001c0410 tail:0xc0001c0400 color:{R:0 G:228 B:48 A:255} direction:1}
🟩 | DEBUG | 23-10-2024 22:27:48:732 | Body: 0xc0001c0400
🟩 | DEBUG | 23-10-2024 22:27:48:748 | body_part: 0xc000180e18, tail: 0xc0000d0000, head: 0xc0000d0010
🟩 | DEBUG | 23-10-2024 22:27:48:748 | body_part: 0xc000015640, tail: 0xc0000d0000, head: 0xc0000d0010
🟩 | DEBUG | 23-10-2024 22:27:48:748 | body_part: 0xc000015650, tail: 0xc0000d0000, head: 0xc0000d0010
🟩 | DEBUG | 23-10-2024 22:27:48:748 | Snake: &{game_ctx:0xc00009e0c0 body:[{X:0 Y:0} {X:0 Y:1} {X:1 Y:1}] head:0xc0000d0010 tail:0xc0000d0000 color:{R:0 G:228 B:48 A:255} direction:1}
🟩 | DEBUG | 23-10-2024 22:27:48:749 | Body: 0xc0000d0000
🟩 | DEBUG | 23-10-2024 22:27:48:765 | body_part: 0xc0001129e0, tail: 0xc0000d0400, head: 0xc0000d0410
🟩 | DEBUG | 23-10-2024 22:27:48:765 | body_part: 0xc0000156f8, tail: 0xc0000d0400, head: 0xc0000d0410
🟩 | DEBUG | 23-10-2024 22:27:48:765 | body_part: 0xc000015708, tail: 0xc0000d0400, head: 0xc0000d0410
🟩 | DEBUG | 23-10-2024 22:27:48:765 | Snake: &{game_ctx:0xc00009e0c0 body:[{X:0 Y:0} {X:0 Y:1} {X:1 Y:1}] head:0xc0000d0410 tail:0xc0000d0400 color:{R:0 G:228 B:48 A:255} direction:1}
🟩 | DEBUG | 23-10-2024 22:27:48:765 | Body: 0xc0000d0400
🟩 | DEBUG | 23-10-2024 22:27:48:782 | body_part: 0xc0000157a8, tail: 0xc0000d0800, head: 0xc0000d0810
🟩 | DEBUG | 23-10-2024 22:27:48:782 | body_part: 0xc0000157b8, tail: 0xc0000d0800, head: 0xc0000d0810
🟩 | DEBUG | 23-10-2024 22:27:48:782 | body_part: 0xc0000157c8, tail: 0xc0000d0800, head: 0xc0000d0810
🟩 | DEBUG | 23-10-2024 22:27:48:782 | Snake: &{game_ctx:0xc00009e0c0 body:[{X:0 Y:0} {X:0 Y:1} {X:1 Y:1}] head:0xc0000d0810 tail:0xc0000d0800 color:{R:0 G:228 B:48 A:255} direction:1}
🟩 | DEBUG | 23-10-2024 22:27:48:782 | Body: 0xc0000d0800
🟩 | DEBUG | 23-10-2024 22:27:48:799 | body_part: 0xc000180e28, tail: 0xc0000d0c00, head: 0xc0000d0c10
🟩 | DEBUG | 23-10-2024 22:27:48:799 | body_part: 0xc000015868, tail: 0xc0000d0c00, head: 0xc0000d0c10
🟩 | DEBUG | 23-10-2024 22:27:48:799 | body_part: 0xc000015878, tail: 0xc0000d0c00, head: 0xc0000d0c10
🟩 | DEBUG | 23-10-2024 22:27:48:799 | Snake: &{game_ctx:0xc00009e0c0 body:[{X:0 Y:0} {X:0 Y:1} {X:1 Y:1}] head:0xc0000d0c10 tail:0xc0000d0c00 color:{R:0 G:228 B:48 A:255} direction:1}
🟩 | DEBUG | 23-10-2024 22:27:48:799 | Body: 0xc0000d0c00
🟩 | DEBUG | 23-10-2024 22:27:48:815 | body_part: 0xc000015918, tail: 0xc0000d1000, head: 0xc0000d1010
🟩 | DEBUG | 23-10-2024 22:27:48:815 | body_part: 0xc000015928, tail: 0xc0000d1000, head: 0xc0000d1010
🟩 | DEBUG | 23-10-2024 22:27:48:815 | body_part: 0xc000015938, tail: 0xc0000d1000, head: 0xc0000d1010
🟩 | DEBUG | 23-10-2024 22:27:48:815 | Snake: &{game_ctx:0xc00009e0c0 body:[{X:0 Y:0} {X:0 Y:1} {X:1 Y:1}] head:0xc0000d1010 tail:0xc0000d1000 color:{R:0 G:228 B:48 A:255} direction:1}
🟩 | DEBUG | 23-10-2024 22:27:48:815 | Body: 0xc0000d1000
🟩 | DEBUG | 23-10-2024 22:27:48:832 | body_part: 0xc0000159d8, tail: 0xc0000d1400, head: 0xc0000d1410
🟩 | DEBUG | 23-10-2024 22:27:48:832 | body_part: 0xc0000159e8, tail: 0xc0000d1400, head: 0xc0000d1410
🟩 | DEBUG | 23-10-2024 22:27:48:832 | body_part: 0xc0000159f8, tail: 0xc0000d1400, head: 0xc0000d1410
🟩 | DEBUG | 23-10-2024 22:27:48:832 | Snake: &{game_ctx:0xc00009e0c0 body:[{X:0 Y:0} {X:0 Y:1} {X:1 Y:1}] head:0xc0000d1410 tail:0xc0000d1400 color:{R:0 G:228 B:48 A:255} direction:1}

Another problem is that I am trying to see if an item of the slice has the same address as the tail or the head but the addresses the range variable gives seem to be completly different.

The repo for the full code is this GitHub - NikosGour/snake_clone_go: A snake clone in Golang using Raylib

Any help with understanding why the addresses keep changing without reassignment is much appriciated!

Looks like it’s an issue with the range iterator, which shared a common address before go1.23, so the pointer variable will change.

func (this *Snake) draw() {
    // this.body is []*raylib.Vector2 will be better
	for _, body_part := range this.body {
        part := body_part
		color := rl.Black
		log.Debug("body_part: %p, tail: %p, head: %p", &body_part, this.tail, this.head)
		if part == this.tail {
			color.R += 0xFF
		}
		if part == this.head {
			color.B += 0xFF
		}

		if color == rl.Black {
			color = this.color
		}

		this.game_ctx.grid.drawCell(int(body_part.X), int(body_part.Y), color)

	}
}

Ye i thought of the solution of body being []*rl.Vector2, but i didn’t want to do it as it would put more complexity in my mind. Found a different solution:

func (this *Snake) draw() {
	for i := range this.body {
		body_part := &this.body[i]
		color := rl.Black
		// log.Debug("body_part: %p, tail: %p, head: %p", body_part, this.tail, this.head)
		if body_part == this.tail {
			color.R += 0xFF
		}
		if body_part == this.head {
			color.B += 0xFF
		}

		if color == rl.Black {
			color = this.color
		}

		this.game_ctx.grid.drawCell(int(body_part.X), int(body_part.Y), color)

	}
}

This is not a good solution. If slice expansion is involved, pointer address inconsistency will also occur.

	ls := []int{1, 2, 3}
	fmt.Println(&ls[0]) //0xc00001e330
	ls = append(ls, []int{4, 5, 6, 7, 8, 9, 10, 11, 12}...)
	fmt.Println(&ls[0]) //0xc00002a840

If Vector2 is a comparable type, then this can also be done:

type Vector2 struct {
	X float32
	Y float32
}

func (this *Snake) draw() {
    // this.tail and this.head is raylib.Vector2 not *raylib.Vector2
    // this.body is []raylib.Vector2
	for _, body_part := range this.body {
		color := rl.Black
		if body_part == this.tail {
			color.R += 0xFF
		}
		if body_part == this.head {
			color.B += 0xFF
		}

		if color == rl.Black {
			color = this.color
		}

		this.game_ctx.grid.drawCell(int(body_part.X), int(body_part.Y), color)
	}
}

This would be a bit more stable if you don’t want to deal with pointers.