Files
knowledge/categories/go.md
T
2019-10-12 16:50:15 +11:00

4.8 KiB
Raw Blame History

Go

pass pointer or value

  • value: Variable must not be modified
  • Variable is a large struct then prefer pointer
  • Variable is a map or slice then prefer value
  • Passing by value often is cheaper

struct

  • make
make(T, args) -> T
  • new
new(T) -> *T
  • a := T{}

array

var a [1]int

Array has a exactly length, can't be modified.

slice

var a []string
[]string{"a", "b"}
[...]string{"a","b"}
  1. Auto increment length
new([]int)
make([]int, 2, 5)
  1. nil is a valid slice which length is 0

Go routine

  • you can run more goroutine vs thread
  • go routine have a faster start up time than thread
  • go routine come with built-in primitives to communicate safely by using channels

Closure

Channel

  • Normal channel
messages := make(chan string)
// _Send_ a value into a channel using the `channel <-`
go func() { messages <- "ping" }()
// channel. Here we'll receive the `"ping"` message
msg := <-messages
  • buffered channel
ch := make(chan Task, 3)

Sync

atomic

Mutex

- sync.Mutex()
- mutex.Lock()
- mutx.Unlock()

RWMutex

A RWMutex is a reader/writer mutual exclusion lock. The lock can be held by an arbitrary number of readers or a single writer. The zero value for a RWMutex is an unlocked mutex.

In other words, readers don't have to wait for each other. They only have to wait for writers holding the lock.

string literals

    `aaa bbb ccc`

panic / recover

sync.Map is concurrent/ thread safe map, normal map isn't

m := new(sync.Map)
m.Store("a", "b")
value, ok := m.Load("a")

Defer to Clean Up

Use defer to clean up resources such as files and locks.

p.Lock()
defer p.Unlock()

if p.count < 10 {
  return p.count
}

p.count++
return p.count

// more readable

Frameworks

db

  • xorm
  • gorm

web

  • beego
  • mux
  • gin
  • go kit
    • full stack micro service framework like spring boot

tools

Tips

slice

  • byte* array //actual data
  • uintgo len
  • uintgo cap

map

  • implement by hash table
  • slice can't be the key of a map, but sized array could. e.g. var a map[[2]int]string

Go has no generics

  • performance
  • complexity
  • If C++ and Java are about type hierarchies and the taxonomy of types, Go is about composition.
  • How to solve
    • use interface
    • use type assertions
    • use reflection

Modify item in range

  • use the array index instead of the value
    for _, e := range array {
        e.field = "foo"
    }

    for idx, _ := range array {
        array[idx].field = "foo"
    }

merge two array

  • a = append(a, b…)
    • must add … to b, otherwise you can only add one item

error handling

  • error type assertion
    if serr, ok := err.(*json.SyntaxError); ok {}
  • better error handling

    • custom error type
type appError struct {
    Error   error
    Message string
    Code    int
}
- concat error check
if err1() != nil || err2() != nil {}
- some error constants
errNotFound = errors.New("Item not found")
switch err {
    case errNotFound:
}

date format

t := time.Now()
fmt.Println(t.String())
fmt.Println(t.Format("2006-01-02 15:04:05"))
  • var _ InterfaceX = &InterfaceXImplementation{}
    • make sure InterfaceXs implementation works

reference types in go

  • map
  • channel
  • slice

value types

  • Array

Read file line by line

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    file, err := os.Open("/path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

commands

test

  • go test ./...
    •  run all tests in current directory and all of its subdirectories
  • go test foo/...
    •  run all tests with import path prefixed with foo/:
  • go test foo...
    • run all tests import path prefixed with foo:
  • go test ...
    • run all tests in your $GOPATH:

REPL

REPL stands for read eval print loop, basically it just like the irb in Ruby.

Wiki: https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop

Useful links