Featured image by Egon Elbre
Happy Easter!
- Continuing to work through https://golangbot.com/learn-golang-series/
- Tutorials 13 to 15.
Maps
- Used as a mapping between key-value pairs. Aka Dictionary in other languages.
- Creating a map
// make(map[keyType]valueType)
nameToAge := make(map[string]int)
// short hand declaration
fileSizes := map[string]int{
"file1.txt": 104,
"file2.txt": 4224, //<-- notice the trailing comma!
}
- Adding items to the map or updating existing values
nameToAge["jannie"] = 23
nameToAge["koos"] = 34
fmt.Println(nameToAge) // map[jannie:23 koos:34]
nameToAge["jannie"] = 42
fmt.Println(nameToAge) // map[jannie:42 koos:34]
- Any comparable type is allowed to be used as a key type. Including your own “struct” types.
- The zero value of a map is
nil
and maps have to be initialized first. - Getting items from a map.
ageForKoos := nameToAge["koos"]
// What about when the key does not exist?
// It returns the zero value of the type
fmt.Println(fileSizes["unknown"]) // 0
- Checking if an item exists in the map.
value, ok := nameToAge["unknown"]
if ok {
... // key "unknown" existed and we received a value in value
}
// or to just check if key is present
_, exists := someMap[someKey]
if exists { ...
- Iterating over the key-value pairs
for key, value := range nameToAge {
...
}
- Map is unordered.
- Use
delete(map, key)
function to delete an item from a map.
delete(nameToAge, "koos")
// No runtime error is raised if you delete a non existent key
// Also delete doesn't return a value to check if the key was deleted
delete(nameToAge, "no-error")
- Use
len(map)
function to get the key count. - NOTE: Maps are reference types (unlike Swift). Meaning that if you assign a map to multiple variables (or pass to functions) then changes made to one will reflect to all of them (since they are references to the actual data).
- Maps can not be compared using
==
operator. The==
operator can only be used to check if the map isnil
Strings
- Strings are implemented as a slice of bytes in Go.
-
string
is the type. - Strings are unicode compliant and encoded as UTF-8.
name := "Andre Jacobs"
fmt.Printf("my name is %s\n", name)
- Use
len()
to get the number of bytes in the string. - NOTE: Iterating over the bytes of a string is not the same as iterating over “characters” or unicode code points (as what Swift does).
- To iterate over the unicode code points, you will use the
rune
type (alias toint32
).
func printCharacters(s string) {
runes := []rune(s)
for i := 0; i < len(runes); i++ {
fmt.Printf("%c ", runes[i])
}
}
// A much better way is to use range
for index, rune := range s {
...
}
- Creating a string from a slice of bytes.
byteSlice := []byte{0x43, 0x61, 0x66, 0xC3, 0xA9}
str := string(byteSlice)
- Creating a string from a slice of runes.
runeSlice := []rune{0x0053, 0x0065, 0x00f1, 0x006f, 0x0072}
str := string(runeSlice)
- Use
RuneCountInString()
function from package “unicode/utf8” to get the number of unicode “characters” in a string. - You can use
==
to check for equality. (May assumption is Go just compares the bytes and no the grapheme clusters like Swift does). - You can concatenate strings using
+
operator. You can also use fmt.Sprintf function. - String are immutable.
Pointers
- Quick recap: A pointer is a variable that stores an address to some location in memory (that can then be mapped to a type).
- Declared using
*T
. - Use
&
to get the address of a variable.
b := 255
var a *int = &b // create a pointer to b
fmt.Printf("Type of a is %T\n", a) // Type of a is *int
fmt.Println("address of b is", a) // address of b is 0xc000018030
- Zero value of a pointer is
nil
. - Allocate a new instance and assign to a pointer using
new
function. - Dereference using
*
just like C.
p := new(int)
fmt.Printf("%T\n", p) // *int
fmt.Println(p) // 0xc000018038
fmt.Println(*p) // 0
*p = 42
fmt.Println(*p) // 42
- Pointers can be passed as function arguments.
- Pointers can also be returned as the result type for a function.
// What do you think this code will do?
func spideySense() *int {
i := 5
return &i
}
// Go is smart enough to save you from the C pitfalls here and
// allocates i on the heap!
- It is more Go idiomatic to pass slices of arrays to functions (instead of passing a pointer to an array).
- Go does not support pointer arithmetic like C does.