Reputation: 2820
I'm currently teaching myself Go, and I'm having trouble understanding a certain behavior:
package main
import (
"fmt"
)
type List struct {
n int
}
func (l List) Increment() {
l.n += 1
l.LogState() // size: 1
}
func (l List) LogState() {
fmt.Printf("size: %v\n", l.n)
}
func main() {
list := List{}
list.Increment()
fmt.Println("----")
list.LogState() // size: 0
}
https://play.golang.org/p/-O24DiNPkxx
LogState
is executed twice. The initial time, during the Increment
call, it prints size: 1
but after Increment
has returned it prints size: 0
. Why are those values different?
Upvotes: 1
Views: 85
Reputation: 12675
The reason your nodes are not added to the original linkedList because you are not using pointer to the struct. So even if the Increment
function in your example code changes the value. The copy of the struct is changed not the actual struct.
You can declare methods with pointer receivers. This means the receiver type has the literal syntax *T for some type T. (Also, T cannot itself be a pointer such as *int.)
If you want to change the linkedlistNode struct counter to show the nodes added to the list you should be using a pointer type receiver on both methdos working to modify the linked list as:
func (l *LinkedList) AddInitialValue(v interface{})
func (l *LinkedList) LogState()
And Inside the main pass an address to the linkedList to use those pointer type receivers as:
func main() {
list := &LinkedList{}
list.AddInitialValue(9)
fmt.Println("----")
list.LogState() // size: 0
}
Working Code Go playground
Note:-
There are two reasons to use a pointer receiver.
- To modify the value that its receiver points to.
- To avoid copying the value on each method call. This can be more efficient if the receiver is a large struct
For more information go through Method Sets
Upvotes: 1
Reputation: 4324
With Increment
and LogState
defined the way you've defined them, you are working only with the copy of the value of List
. This means that if you make some changes inside Increment
function, they are visible only inside Increment
's function scope and only for the remainder of that particular scope's existence. To confirm you are always working with a copy of of the initial List
value, you can log &list
before executing Increment
function and &l
inside the same function.
If you want to make changes permanent, you should work with a pointer to a memory address. That means your your function should be defined like this:
func (l *List) Increment()
func (l *List) LogState()
This way, you are passing a memory reference (pointer to an address in memory) and every time you change a value of l
, you are changing it on the passed memory reference and it reflects everywhere.
Upvotes: 1