Man

Development & AI | Alper Akgun

Learn Go by example - basics

September, 2023

The Go programming language, also known as Golang, is a statically typed, compiled language that is simple, efficient, and lightweight. It's designed to be simple to understand with its simplified syntax and clean, straightforward syntax, making it a great choice for network services and systems programming. In GitLab we use Go for a lot of projects, whenever we need a small microservice and when performance matters.

In this blog, I study through the examples at use https://gobyexample.com

Here is a simple HTTP server written in Go:

package main
import "net/http"

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

http.ListenAndServe(":8080", http.HandlerFunc(handler))
            

Or a concurrent programming example using goroutines:

package main
import "time"
func say(s string) {
    time.Sleep(time.Second)
    println(s)
}
func main() {
    go say("World")
    go say("Hello")
}

Hello, world.

package main

import "fmt"

func main() {
    fmt.Println("Hello, Multiverse!")
}
go run hello-world.go
$ go build hello-world.go
$ ls
hello-world    hello-world.go

$ ./hello-world

Golang value types include strings, integers, floatds, booleans etc.

package main

import "fmt"

func main() {
    fmt.Println("Hello " + "Alice")

    fmt.Println("41 + 1 =", 41+1)
    fmt.Println("7.28/3.14 =", 7.28/3.14)

    fmt.Println(true && false)
    fmt.Println(true || false)
    fmt.Println(!true)
}

In Golang you must declare variables explicitly.

package main

import "fmt"

func main() {
    var str = "first"
    fmt.Println(str)

    var n, m int = 41, 1
    fmt.Println(n, m)

    var finished = true
    fmt.Println(finished)

    var count int
    fmt.Println(count)

    f := "apple"
    fmt.Println(f)
}            

Constants are similar to variables as usual.

package main

import (
    "fmt"
    "math"
)

const s string = "HELLO CONSTANTS"

func main() {
    fmt.Println(s)

    const n = 300000000

    const m = 3e20 / n
    fmt.Println(m)

    fmt.Println(int64(m))

    fmt.Println(math.Sin(m))
}

For loops are straightforward:

package main

import "fmt"

func main() {

    i := 0
    for i <= 7 {
        fmt.Println(i)
        i = i + 1
    }

    for j := 8; j <= 42; j++ {
        fmt.Println(j)
    }

    for {
        fmt.Println("forever?")
        break
    }

    for n := 0; n <= 7; n++ {
        if n % 3 == 0 {
            continue
        }
        fmt.Println(n)
    }
}            

Branching can be achieved using if/else or switch statements.

package main

import "fmt"

func main() {

    if 7 > 3 {
        fmt.Println("7 is greater")
    } else {
        fmt.Println("3 is greater")
    }

    if num := -1; num < 0 {
        fmt.Println(num, "is negative")
    } else if num < 10 {
        fmt.Println(num, "has 1 digit")
    } else {
        fmt.Println(num, "has multiple digits")
    }

    switch time.Now().Weekday() {
    case time.Saturday, time.Sunday:
        fmt.Println("It's the weekend")
    default:
        fmt.Println("It's a weekday")
    }

    i := 3
    fmt.Print("Write ", i, " as ")
    switch i {
    case 1:
        fmt.Println("bir")
    case 2:
        fmt.Println("iki")
    }
}

            

In Golang, a string is a read-only slice of bytes. The language and the standard library treat strings as containers of text encoded in UTF-8. In other languages, strings are made of “characters”. In Go, the concept of a character is called a rune - it’s an integer that represents a Unicode code point.

package main
package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {

    const s = "Hello"

    fmt.Println("Len:", len(s))

    for i := 0; i < len(s); i++ {
        fmt.Printf("%x ", s[i])
    }
    fmt.Println()

    fmt.Println("Rune count:", utf8.RuneCountInString(s))

    for idx, runeValue := range s {
        fmt.Printf("%#U starts at %d\n", runeValue, idx)
    }

    for i, w := 0, 0; i < len(s); i += w {
        runeValue, width := utf8.DecodeRuneInString(s[i:])
        fmt.Printf("%#U starts at %d\n", runeValue, i)
        w = width

        examineRune(runeValue)
    }
}

func examineRune(r rune) {

    if r == 'a' {
        fmt.Println("found a")
    } else if r == 'b' {
        fmt.Println("found b")
    }
}
            

In Go arrays are numbered sequence of elements, but "slices" are more commonly used.

package main

import "fmt"

func main() {

    var x [5]int
    fmt.Println("emp:", x)

    x[4] = 100
    fmt.Println("set:", x)
    fmt.Println("get:", x[4])

    fmt.Println("len:", len(x))

    y := [5]int{1, 2, 3, 4, 5}
    fmt.Println("numbers:", y)

    var twoD [4][3]int
    for i := 0; i < 4; i++ {
        for j := 0; j < 3; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
}            

Slices are more powerful in Golang than arrays.

package main

import (
    "fmt"
    "slices"
)

func main() {

    var sl []string
    fmt.Println("not initialized:", sl, sl == nil, len(sl) == 0)

    sl = make([]string, 3)
    fmt.Println("emp:", sl, "len:", len(sl), "cap:", cap(sl))

    sl[0] = "a"
    sl[1] = "b"
    sl[2] = "c"
    fmt.Println("set:", sl)
    fmt.Println("get:", sl[2])

    fmt.Println("length of s:", len(sl))

    sl = append(sl, "d")
    sl = append(sl, "e", "f")
    fmt.Println("appended:", sl)

    c := make([]string, len(s))
    copy(c, s)
    fmt.Println("cpy:", c)

    l := sl[2:5]
    fmt.Println("mid:", l)

    l = s[:5]
    fmt.Println("right:", l)

    l = s[2:]
    fmt.Println("left:", l)

    st := []string{"o", "p", "r"}
    fmt.Println("dcl:", st)

}
            

Maps in golang are like the same in python, objects in JavaScript, and hashes in Ruby.

package main

import (
    "fmt"
    "maps"
)

func main() {

    m := make(map[string]int)

    m["el1"] = 7
    m["el2"] = 13

    fmt.Println("map:", m)

    v1 := m["el1"]
    fmt.Println("v1:", v1)

    v3 := m["el3"]
    fmt.Println("v3:", el3)

    fmt.Println("len:", len(m))

    delete(m, "el2")
    fmt.Println("map:", m)

    clear(m)
    fmt.Println("map:", m)

    _, prs := m["el2"]
    fmt.Println("prs:", prs)

    values := map[string]int{"foo": 1, "bar": 2}
    fmt.Println("map:", values)

}            

Ranges allow iteration on a data structure.

package main

import "fmt"

func main() {

    nums := []int{42, 43, 44}
    sum := 0
    for _, num := range nums {
        sum += num
    }
    fmt.Println("Sum: ", sum)

    for i, num := range nums {
        if num == 3 {
            fmt.Println("index:", i)
        }
    }

    kvs := map[string]string{"a": "avocado", "b": "banana"}
    for k, v := range kvs {
        fmt.Printf("%s -> %s\n", k, v)
    }

    for k := range kvs {
        fmt.Println("key:", k)
    }

    for i, c := range "hello" {
        fmt.Println(i, c)
    }
}
            

Functions are a core piece in Golang.

package main

import "fmt"

func add(a int, b int) int {

    return a + b
}

func add3(a, b, c int) int {
    return a + b + c
}

func returnTwo() (int, int) {
    return 3, 7
}

package main

import "fmt"

func sum(nums ...int) {
    fmt.Print(nums, " ")
    total := 0

    for _, num := range nums {
        total += num
    }
    fmt.Println(total)
}

func seq() func() int {
    i := 0
    return func() int {
        i++
        return i
    }
}

func factorial(n int) int {
    if n == 0 {
        return 1
    }
    return n * factorial(n-1)
}

func main() {

    res := add(41, 2)
    fmt.Println("41 + 2 =", res)

    res = add3(37, 2, 3)
    fmt.Println("37 + 2 + 3 =", res)

    a, b := returnTwo()
    fmt.Println(a)
    fmt.Println(b)

    _, c := returnTwo()
    fmt.Println(c)

    sum(1, 2)
    sum(1, 2, 3)

    nums := []int{1, 2, 3, 4}
    sum(nums...)


    nextInt := seq()

    fmt.Println(nextInt())
    fmt.Println(nextInt())

    newInts := seq()
    fmt.Println(newInts())


    fmt.Println(factorial(7))

    var fibonacci func(n int) int

    fibonacci = func(n int) int {
        if n < 2 {
            return n
        }

        return fibonacci(n-1) + fibonacci(n-2)
    }

    fmt.Println(fibonacci(7))
}