Development & AI | Alper Akgun
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))
}