3

I am trying to wrap my head around pointer in go. I have this code right here

package main

import (
    "fmt"
)

// LinkedList type
type LinkedList struct {
    data int
    next *LinkedList
}

// InsertList will insert a item into the list
func (node *LinkedList) InsertList(data int) {
    newHead := LinkedList{data, node}
    node = &newHead
}

func main() {
    node := &LinkedList{}
    node.InsertList(4)
    fmt.Printf("node = %+v\n", node)
}

and The output is

node = &{data:0 next:<nil>}

I would like to understand that why is node = &newHead my InsertList method did not reference the node pointer to a different struct at all

3 Answers 3

5

The receiver node is passed by value just like other parameters, so any changes you make in the function are not seen by the caller. If you want a function to modify something that exists outside the function, the function needs to be dealing with a pointer to that object. In your case, node is a pointer, but what you really want is a pointer to something that represents the list itself. For example:

package main

import (
    "fmt"
)

type LinkedListNode struct {
    data int
    next *LinkedListNode
}

type LinkedList struct {
    head *LinkedListNode
}

// InsertList will insert a item into the list
func (list *LinkedList) InsertList(data int) {
    newHead := &LinkedListNode{data, list.head}
    list.head = newHead
}

func main() {
    var list LinkedList
    list.InsertList(4)
    fmt.Printf("node = %+v\n", list.head)
    list.InsertList(7)
    fmt.Printf("node = %+v\n", list.head)
}
Sign up to request clarification or add additional context in comments.

3 Comments

hmm make senses. Thank you
@HuyLe, Go actually makes pointers simpler than in certain other languages because it does not contain pass-by-value/pass-by-reference distinction nonsense. In Go, any value of any type is always passed by value (copied)--on assignment and when passed as a parameter to a function. A pointer is just a value, too, just it defined to store an address of the memory location of some other value.
@HuyLe, Hence when you pass a pointer into a function, changing the pointer value itself in its code has little sense as you just re-write the address stored in it, and as with any other value, this does not affect the caller in any way. But you can use the pointer value to dereference (or "chase") it--to get hold onto the value kept at the address stored in the poiner value. That value you can mutate in arbitrary ways.
4

Just change the value reference argument point to

func (node *LinkedList) InsertList(data int) {
    newHead := LinkedList{data, node}
    *node = newHead   //<- dereference here 
}

Comments

2

Think of it like this: every variable must be stored at some location in memory, and you can use a pointer to store that location rather than just the variable itself.

To get or set the value at that location using the pointer, you need to use the "indirection" operator. For example, *node will get the LinkedList at the location that node points to, and *node = newHead will set the LinkedList at the location that node points to.

You can also point the pointer to a new memory location, but that change will only be visible in the current scope. In your case, that means node = &newHead only affects the node pointer in InsertList, not the node pointer in main.

Here's a simpler example using normal functions, though the same rules apply for methods:

// Changes the value `x` points to
func modifyValue(x *int) {
    fmt.Printf("  modifyValue: x=%3d @ %p\n", *x, x)
    *x = 1
    fmt.Printf("  modifyValue: x=%3d @ %p\n", *x, x)
}

// Changes the pointer `x` itself
func modifyPointer(x *int) {
    fmt.Printf("modifyPointer: x=%3d @ %p\n", *x, x)
    n := 1
    x = &n
    fmt.Printf("modifyPointer: x=%3d @ %p\n", *x, x)
}

func main() {
    x := 200
    fmt.Printf("         main: x=%3d @ %p\n\n", x, &x)
    modifyPointer(&x)
    fmt.Printf("         main: x=%3d @ %p\n\n", x, &x)
    modifyValue(&x)
    fmt.Printf("         main: x=%3d @ %p\n\n", x, &x)
}

Output:

         main: x=200 @ 0x1040e0f8

modifyPointer: x=200 @ 0x1040e0f8
modifyPointer: x=  1 @ 0x1040e134
         main: x=200 @ 0x1040e0f8

  modifyValue: x=200 @ 0x1040e0f8
  modifyValue: x=  1 @ 0x1040e0f8
         main: x=  1 @ 0x1040e0f8

Playground link

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.