Golang

Pass by value or reference

The official Go site FAQ states,  “As in all languages in the C family, everything in Go is passed by value”. This is because the function gets a copy of everything that is passed in.

Is there such thing as pass by reference in Go?

There are different views  as to what is exactly pass by reference to Go.  Some strongly maintain there is no such thing as pass by reference. In C++ terms, the actual meaning of pass by reference is you pass a reference or a pointer to the actual data structure rather the data itself. The function then can modify the value of the argument using that reference.

In Go when I pass a pointer to a struct for example, whether its a copy to the pointer or not, I am not passing the struct itself but a pointer or a reference to it.  I can modify the actual struct using the pointer. In my view, that fits the definition of pass by reference.

When to pass a pointer?

We don’t need to pass pointers to map and slices  as they are already descriptors that contain pointers to the actual map or slice data.

Compelling arguments to use pointer receiver and pass by reference:

  • You want to modify the receiver. With value receivers you can’t modify the struct itself
  • Its is a big struct. It will cost to deep copy the struct.

When you pass a slice to a function, since it is a pointer to an array you just get a copy of the slice structure. It will still point to the same underlying array segment. So any modifications made to the slice within the function will be seen outside.

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

However, if you append an element, remember that a new slice is created and elements are copied over so you will lose the elements if this happens within a function so you must return a slice. E.g. append from the stdlib returns a new slice.

Whatever it is you choose to use, stay consistent. Coming from a C++ background, I always thought pass by reference is cheaper than passing by value. But apparently it is not always the case in Go.

Interesting Reads:

http://goinbigdata.com/golang-pass-by-pointer-vs-pass-by-value/

Uncategorized

Golang Data Types

Basic data types

bool 
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // same as for uint8
rune // represents a Unicode code point
float32 float64
complex64 complex128

int

int is a signed integer type that is at least 32 bits in size. It is a distinct type, however, and not an alias for, say, int32

An int is either 32 or 64 bits depending on the platform. So it maybe better to be specific if developing and host machines differ.

Rune

Strings are made up of “runes” rather than chars. Rather than having char and wchar for characters and unicode characters, a rune is a “code point” as defined in the Unicode standard. Internally it is  a 32-bit representation.

nihao := "你好" 
for index, runeValue := range nihao {
fmt.Printf("Char %#U Byte position %d\n", runeValue, index)
}
  • String to array of runes
runes := []rune(s)
  • rune array to string
str := string(runes)

Slice

A slice consists of a pointer to an array segment, length of the segment and its capacity i.e. the maximum length of the segment.

  • Create
b = make([]T, len(a))

Note that since the zero value of a slice is nil, you don’t need to explicitly make a slice, you can just declare it like below.

  • Add element
var s []int      // s := make([]string, 0) 
s = append(s, 1) //add one element
s = append(s, 2,3,4) //add multiple
s = append(s, s1…) // append another slice
  • Delete element
s[len(s)-1] //remove last element
  • Iterate over a slice
for index, value := range s { 
fmt.Println(index, value)
}
  • Copy

Use copy to deep copy all slice elements from one slice to another. Simply assigning one slice will only change the reference.

a := []int{1, 2}
b := []int{3, 4}

a = b // changes a to refer to the location of b

copy(a,b) //actually copy values from b to

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

Two dimensional slices

Slices in Go are one-dimensional. We have to compose it to form two-dimensional arrays.

matrix := make([][]int, row) 
for m := range matrix {
matrix[m] = make([]int, col)
}

When you pass a slice to a function, since it is a pointer to an array you just get a copy of the slice structure. It will still point to the same underlying array segment. So any modifications made to the slice within the function will be seen outside.

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

However, if you append an element, remember that a new slice is created and elements are copied over so you will lose the elements if this happens within a function so you must return a slice. E.g. append from the stdlib returns a new slice.

  • Creating and initializing a 2d slice
graph := [][]int{  
{0, 4, 0, 0, 0},
{4, 0, 8, 0, 0},
{0, 8, 0, 7, 0},
{0, 0, 7, 0, 9},
{0, 0, 0, 9, 0},
}

Map

The built-in map type implements a hash table. Map is also a reference type like slices. Maps, like channels, but unlike slices, are just pointers to runtime types. As you saw above, a map is just a pointer to a runtime.hmap structure. So when we declare a map using var, its value will be nil until initialized using make. Attempts to access a nil map will result in a panic.

  • Create
x := make(map[int]int)

You could initialize a map with values. In that case, you don’t have to use make

colorCodes := map[string]string{  
"BRONZE":   "E0001B",
"GOLD":    "A89968",
"SILVER":   "888B8D",
}
fmt.Println(colorCodes["BRONZE"])
  • Add element to a map
x[1] = 10
  • Delete element
delete(x, 1)
  • Find value
val, ok := x[key]
  • Iterating
for key, val:= range x {     
println("Key:", key, "Value:", val ,"Value:", m[k])
}
  • Size
len(m)
  • Copy

To copy a map to another, we need to traverse the map and do a deep copy. Just assigning a map to another will not copy contents over.

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

All operations on a map are in constant time.

You don’t need to use refeences with a map. Map types are reference types like slices.  If you pass a map to a function and add key-value pairs or update values , it will be reflected outside a function. When using maps in concurrent routines, we may need to add locks to ensure data integrity.

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

Struct

struct is a collection of fields.

A struct can have methods defined on it. There are two kinds of methods that can be defined on a  struct, a value receiver and a pointer receiver.

type T struct { 
a int
}

func (tv T) Mv(a int) int {
return 0
} // value receiver

func (tp *T) Mp(f float32) float32 {
return 1
} // pointer receiver

It all comes down which one is better for the problem at hand.

Related blog posts for Structs:

Constants

There are boolean constantsrune constantsinteger constantsfloating-point constantscomplex constants, and string constants. Rune, integer, floating-point, and complex constants are collectively called numeric constants.

A constant expression may contain only constant operands and are evaluated at compile time. As such, there is no such thing as array constant in Go. Slices and arrays are always evaluated during runtime. They can only be defined as variables.