Max Blog

Discipline equals Freedom

Stack in Go

package main import ( "fmt" ) type Node struct { Value int Next *Node } var size = 0 var stack = new(Node) func Push(v int) bool { if stack == nil { stack = &Node{v, nil} size = 1 return true } temp := &Node{v, nil} temp.Next = stack stack = temp size++ return true } func Pop(t *Node) (int, bool) { if size == 0 { return 0, false } if size == 1 { size = 0 stack = nil return t.

Queue in Go

package main import ( "fmt" ) type Node struct { Value int Next *Node } var size = 0 var queue = new(Node) func Push(t *Node, v int) bool { if queue == nil { queue = &Node{v, nil} size++ return true } t = &Node{v, nil} t.Next = queue queue = t size++ return true } func Pop(t *Node) (int, bool) { if size == 0 { return 0, false } if size == 1 { queue = nil size-- return t.

Linked list in Go

package main import ( "fmt" ) type Node struct { Value int Next *Node } var root = new(Node) func addNode(t *Node, v int) int { if root == nil { t = &Node{v, nil} root = t return 0 } if v == t.Value { fmt.Println("Node already exists:", v) return -1 } if t.Next == nil { t.Next = &Node{v, nil} return -2 } return addNode(t.Next, v) } func traverse(t *Node) { if t == nil { fmt.

Hash table in Go

package main import ( "fmt" ) const SIZE = 15 type Node struct { Value int Next *Node } type HashTable struct { Table map[int]*Node Size int } func hashFunction(i, size int) int { return (i % size) } func insert(hash *HashTable, value int) int { index := hashFunction(value, hash.Size) element := Node{Value: value, Next: hash.Table[index]} hash.Table[index] = &element return index } func traverse(hash *HashTable) { for k := range hash.

Binary trees in Go

package main import ( "fmt" "math/rand" "time" ) type Tree struct { Left *Tree Value int Right *Tree } func traverse(t *Tree) { if t == nil { return } traverse(t.Left) fmt.Print(t.Value, " ") traverse(t.Right) } func create(n int) *Tree { var t *Tree rand.Seed(time.Now().Unix()) for i := 0; i < 2*n; i++ { temp := rand.Intn(n * 2) t = insert(t, temp) } return t } func insert(t *Tree, v int) *Tree { if t == nil { return &Tree{nil, v, nil} } if v == t.

Doubly linked list in Go

package main import ( "fmt" ) type Node struct { Value int Previous *Node Next *Node } func addNode(t *Node, v int) int { if root == nil { t = &Node{v, nil, nil} root = t return 0 } if v == t.Value { fmt.Println("Node already exists:", v) return -1 } if t.Next == nil { temp := t t.Next = &Node{v, temp, nil} return -2 } return addNode(t.Next, v) } func traverse(t *Node) { if t == nil { fmt.

rune in Go

A rune is an int32 value, and therefore it is a Go type that is used for representing a Unicode code point. A Unicode code point or code position is a numerical value that is usually used for representing single Unicode characters. NOTE: You can consider a string as a collection of runes. A rune literal is a character in single quotes. You may also consider a rune literal as a rune constant.

Using the new keyword

Go supports the new keyword that allows you to allocate new objects. However, there is a very important detail that you need to remember about new: new returns the memory address of the allocated object. Put simply, new returns a pointer! You can create a fresh aStructure variable as follows: pS := new(aStructure) After executing the new statement, you are ready to work with your fresh variable that has its allocated memory zeroed, but not initialized.

The constant generator iota

The constant generator iota is used for declaring a sequence of related values that uses incrementing numbers without the need to type each one of them explicitly. const ( Zero Digit = iota One Two Three Four ) Here you see the definition of a constant generator iota based on Digit, which is equivalent to the following declaration of four constants: const ( Zero = 0 One = 1 Two = 2 Three = 3 Four = 4 )

Byte Slices

A byte slice is a slice where its type is byte. You can create a new byte slice named s as follows: s := make([]byte, 5) There is nothing special in the way that you can access a byte slice compared to the other types of slices. It is just that byte slices are used in file input and output operations.

General Go coding advices

The following list offers practical advices that will help you write better Go code: If you have an error in a Go function, either log it or return it, do not do both unless you have a really good reason for doing so! Go interfaces define behaviors, not data and data structures. Use the io.Reader and io.Writer interfaces because they make your code more extensible. Make sure that you pass a pointer to a variable of a function only when needed.

Find out Go Environment

package main import ( "fmt" "runtime" ) func main() { fmt.Print("You are using ", runtime.Compiler, " ") fmt.Println("on a", runtime.GOARCH, "machine") fmt.Println("Using Go version", runtime.Version()) fmt.Println("Number of CPUs:", runtime.NumCPU()) fmt.Println("Number of Goroutines:", runtime.NumGoroutine()) } xecuting goEnv.go on a macOS High Sierra machine with Go version 1.9.2 will create the following output: $ go run goEnv.go You are using gc on a amd64 machine Using Go version go1.9.2 Number of CPUs: 8 Number of Goroutines: 1

Error in Go

Error handling Error handling is a very important feature of Go because almost all Go functions return an error message or nil, which is the Go way of saying whether there was an error condition while executing a function or not. if err != nil { log.Println(err) os.Exit(10) }

Writing to log files

Generally speaking, using a log file to write some information is considered a better practice than writing the same output on the screen for two reasons: The output does not get lost as it is stored in a file You can search and process log files using Unix tools such as grep(1), awk(1), and sed(1), which cannot be done when messages are printed on a Terminal window

Working with command-line arguments

package main import ( "fmt" "os" "strconv" ) func main() { if len(os.Args) == 1 { fmt.Println("Please give one or more floats.") os.Exit(1) } arguments := os.Args min, _ := strconv.ParseFloat(arguments[1], 64) max, _ := strconv.ParseFloat(arguments[1], 64) for i := 2; i < len(arguments); i++ { n, _ := strconv.ParseFloat(arguments[i], 64) if n < min { min = n } if n > max { max = n } } fmt.