Basic question on slices and scope

Dear friends,

I have been reading and watching a lot on scope, but there’s one thing that keeps bugging me in golang. Why is that slices seem to defy the ordinary rules of scope? The two code blocks down here are somewhat identical, with the difference that one uses a slice and the other one a normal variable.

The result is that the functie changeMe() in the first block of code (with the slice) seems to be able to change a value contained in slice ‘m’ beyond it’s own scope, whereas the same function in the second block of code only changes the value of ‘z’ within it’s own scope, and not the value of ‘m’ in the main scope.

Could anyone enlighten me as to how this works and why this is?

Thanks so much in advance!

package main

import "fmt"

func main() {
	m := make([]string, 1, 25)
	fmt.Println(m) // [ ]
	changeMe(m)
	fmt.Println(m) // prints [Todd], so changeMe() changed a value beyond it's own scope
}

func changeMe(z []string) {
	z[0] = "Todd"
	fmt.Println(z) // [Todd]
}

import "fmt"

func main() {
	m := "test"
	fmt.Println(m) // prints test
	changeMe(m)
	fmt.Println(m) //prints test, so changeMe() wasn't able to change a value beyond it's own scope
}

func changeMe(z string) {
	z = "Todd"
	fmt.Println(z) // prints Todd
}

Slices are essentially pointers to arrays, plus bookkeeping: https://blog.golang.org/go-slices-usage-and-internals

Consider also:

package main

import "fmt"

type T struct {
	s string
}

func main() {
	m := T{"test"}
	fmt.Println(m) // "{test}"

	changeMe1(m)
	fmt.Println(m) // still "{test}"

	changeMe2(&m)
	fmt.Println(m) // now "{Todd}"
}

func changeMe1(z T) {
	z.s = "Todd"
}

func changeMe2(z *T) {
	z.s = "Todd"
}

And:

package main

import "fmt"

func main() {
	m := "test"
	fmt.Println(m) // "test"

	changeMe1(m)
	fmt.Println(m) // still "test"

	changeMe2(&m)
	fmt.Println(m) // now "Todd"
}

func changeMe1(z string) {
	z = "Todd"
}

func changeMe2(z *string) {
	*z = "Todd"
}

That is, it’s not a scope thing, it’s a pointer thing. Slices and maps act like pointers / “references”.

2 Likes

Great, thanks! I think I get it. So in essence slices and maps point to a memory address, which content is then changed by the ChangeMe?

You can compare it with C language,this impact is similar.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.