Go Basic
Golang Pass by value vs Pass by reference
Basic of Golang Pointer
Pass by value and Pass by reference are an important thing that needs to be careful of when working with Programming Language that supports us to access a ‘pointer’ value like Java, C#, C/C++, Go, etc.
When you create a method/function with parameters, the data type of the parameters can be set with a normal data type or a pointer. This will make the difference in the argument that passed into the method:
- Pass by value will pass the value of the variable into the method, or we can say that the original variable ‘copy’ the value into another memory location and pass the newly created one into the method. So, anything that happens to the variable inside the method will not affect the original variable value.
- Pass by reference will pass the memory location instead of the value. In other words, it passes the ‘container’ of the variable to the method so, anything that happens to the variable inside the method will affect the original variable.
In a nutshell,
Pass by value will copy the value, Pass by reference will give the memory location.
I found a good illustration from the internet to make everything clearer.
Pass by Value vs Pass by Reference in Go
In Go programming language, we have access to deal with a pointer which means we must understand how the Pass by Value and Pass by Reference work in go, we will separate it into 3 sections: Basic
, Referenced
, Function
.
Repository: https://github.com/david-yappeter/go-passbyvalue-passbyreference
Basic Data Type
Output:
## INIT
Memory Location a: 0xc0000120a8, b: 0xc0000120c0
Value a: 0, b: 0## 'Add' Function
Before Add, Memory Location: 0xc0000120f0, Value: 0
After Add, Memory Location: 0xc0000120f0, Value: 1## 'AddPtr' Function
Before AddPtr, Memory Location: 0xc0000120c0, Value: 0
After AddPtr, Memory Location: 0xc0000120c0, Value: 1## FINAL
Memory Location a: 0xc0000120a8, b: 0xc0000120c0
Value a: 0, b: 1
In the first example, we will work on the basic data types. As we can see we have 2 functions:
Add(x int)
which take an integer as the parameter.AddPtr(x *int)
which takes a pointer integer as the parameter.
The memory location of a
and b
cannot be predicted but we can track them down by printing their memory location.
In the Add
method, the memory location of the value is not the same as a
from the main()
because Go copy the value of a
and initialize a new memory location, so if we change the value x++
, a will still be 0
. The final output of a
is 0
because it is Pass by value.
In the AddPtr
method, the memory location of the value is the same as b
so we know that it shares the same ‘container’, everything that we do to x
inside AddPtr
will affect b
value, we try to add the value of x in *x++
. The final output of b
is 1
which changed because of Pass by reference.
Other basic data types like int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, string, bool, byte, rune, Array, Structs
. Array and Struct have the same property with basic data types.
Referenced Data Type
Output:
======================
SLICES
======================
Init
ArrInt: [1 2 3 4 5], SliceInt: [4 5]After
ArrInt: [1 2 3 10 5], SliceInt: [10 5]
======================
MAP
======================
Init
emptyMap : map[]
After
emptyMap : map[this is a new value:100]
In this second example, Slices
from an array will have the memory location of the array, so if we change the value of the Slices
it will affect the array value, and map
data type is Pass by Reference by default, so anything changed inside the function will change the original map value. If we want to do a Pass by Value for map
we can use copy
which will make a new variable of the map
so the original variable will not take any effect from the method. chan
or channel is also referenced data type.
Function
Output:
================
MAIN
================
Memory Location: 0xc000128058
Value: {IntVal:0}====================
Func Add
====================
Memory Location 0xc000128098
Value Before: {IntVal:0}
Value After: {IntVal:1}================
AFTER Func Add()
================
Value: {IntVal:0}====================
Func AddPtr
====================
Memory Location 0xc000128058
Value Before: &{IntVal:0}
Value After: &{IntVal:1}================
AFTER Func AddPtr()
================
Value: {IntVal:1}================
FINAL
================
Value: {IntVal:1}
In the last example, we will work on Struct Function
. The difference is on the struct itself instead of the variable inside the struct. When we make a struct function, we declare the struct as the prefix of the function, for example func (s struct) FuncName()
or func (s *struct) FuncName()
. The difference is, the struct that uses in the function, if we use pointer one, it will give us the original struct, so anything that happens to the value of the struct will have an effect on the original one, and the function without a pointer will make a copy of the struct and pass it into the function. So, if anything happens to the value of the struct, it will not affect the original struct.
This is the end of this article, hope it helps you understand better about Pass by Value vs Pass by Reference especially in Go programming language.