3

While I was fooling around with closures, I stumbled upon this behavior. I can't wrap my head around it.

This code snippet works:

func main(){
    var a string = "foo"
    var b *string
    var c string = "bar"
    b = &c

    fmt.Printf("%s %s\n", a, *b)

    a = "hello"
    *b = "world"

    fmt.Printf("%s %s\n", a, *b)
}

Whereas this does not:

func main(){
    var a string = "foo"
    var b *string
    *b = "bar"

    fmt.Printf("%s %s\n", a, *b)

    a = "hello"
    *b = "world"

    fmt.Printf("%s %s\n", a, *b)
}

https://play.golang.org/p/NHw3X__Wtd

Could someone much cleverer than me please explain.

2
  • This video explains C pointers, but the lesson applies well to go too. youtube.com/watch?v=mnXkiAKbUPg Commented Jun 25, 2016 at 6:17
  • Thank you for the video. I knew how it was working in C, I just never realized that it would be the same in go. Stupid me. But pointee for the referenced object was new. Actually very fitting. Commented Jun 25, 2016 at 6:36

1 Answer 1

2

Each variable is initialized to the zero value of its type if you don't explicitly specify an initial value. Zero value for all pointer types is nil which means it does not point to anything (yet).

You may assign an address (pointer value) at any time to a variable of pointer type. But until you initialize your pointer variable (to anything other than nil), it points to nothing and thus you can't assign anything to where it points to (because that is "nothing").

In order to set the pointed value, initialize it first so it will actually point to somewhere which you can set/change. This initialization may be the address of some other variable (of the same type as the pointed type - called the element type), or the address of some newly allocated zero value of the pointed type returned by the builtin new() function.

This line

var b *string

just creates a new variable b of type *string, but it doesn't specify any initial value, so b will be initialized to nil. It does not point to anything (or to anywhere). If you attempt to set the pointed value:

var b *string
*b = "bar"

You get a runtime panic:

panic: runtime error: invalid memory address or nil pointer dereference

For you to be able to set the pointed value, you need to initialize it with a non-nil pointer value, e.g.:

b = new(string)

After this you can now set the pointed value:

*b = "world"

Note that when you do:

var b *string
var c string = "bar"
b = &c

This creates a variable b of type *string which will get the zero value nil. And creates a variable c of type string, and initializes it with the value "bar". And after that takes the address of c and stores it in the pointer variable b. Now after this if you modify the value pointed by b, that will "also" modify the value of the variable c because b points to c (or more precisely b stores the memory address where c is). So if after this you do:

*b = "world"

And you print the value of both c and *b, both will be "world":

fmt.Println(c, *b) // Prints "world world" 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.