閱讀 A Tour of Go 的重點摘要。

Basic

  • Packages : 程式從 package main 開始。
  • Import
  • Exported Names : package 中的首字母大寫對象會被導出。
  • Function :
    func add(x int, y int) int { ... }
    func add(x, y int) int { ... }       // 也可以這樣寫
    func swap(x, y string) (string, string) { ... }  // 返回多個值
    // named results
    func split(sum int) (x, y int) { 
      ...
      return
    }
    
  • Variables :
    var i, j int = 1, 2  // 類型寫在後面,可初始化值
    var c, python, java = true, false, "no!"  // 也可用初始值決定類型
    k := 3               // 短聲明,等同 var k int = 3,不可寫在函式外。
    
  • Basic Types :
    bool
    string
    int  int8  int16  int32  int64
    uint uint8 uint16 uint32 uint64 uintptr
    byte // uint8 的別名
    rune // int32 的別名
       // 代表一個Unicode碼
    float32 float64
    complex64 complex128
    
  • Type Conversions : 必須顯式轉換類型,不會隱式自動轉換。
    i := 42
    f := float64(i)
    
  • Constants : const Pi = 3.14, 不可用 := 語法

Flow Control

  • for
    for i := 0; i < 10; i++ { ...
    for       ; i < 10;     { ...    // 也可以留空
    // 類似 while 的效果
    sum := 0
    for sum < 100 { ...
    
  • if : 可在 if 判斷前運行一個語句,v的作用域只在 if else 範圍內。
    if v := math.Pow(x, n); v < lim {
    
  • switch : 除非以 fallthrough 語句結束,否則每個 case 會自動終止。
    switch os := runtime.GOOS; os {
      case "darwin": ...
      case "linux": ...
      default: ...
    }
    // 沒有條件的 switch 就像是比較清楚的 if-then-else 寫法
    switch {
      case t.Hour() < 12: ...
      case t.Hour() < 17: ...
      default: ...
    }
    

More Types

  • struct :
type Vertex struct {
	X int
	Y int
}

v := Vertex{1, 2}
p := &v
p.X = 987
fmt.Println(v.X)
  • pointer : golang 有指標,但沒有指標運算。
  • struct literals
    var (
      p = Vertex{1, 2}   // has type Vertex
      q = &Vertex{1, 2}  // has type *Vertex
      r = Vertex{X: 1}   // Y:0 is implicit
      s = Vertex{}       // X:0 and Y:0
    )
    
  • new : new(T) 分配零初始化的 T 值,並返回它的指針。
    var t *T = new(T)
    t := new(T)
    
  • array : 陣列的長度是類型的一部分,不能改變大小
    var a [10]int
    
  • slice : []T 指向一個陣列,包含長度信息。s[lo:hi] 表示從 lo 到 hi-1 的 slice 元素
    a := make([]int, 5)     // len(a)=5
    b := make([]int, 0, 5)  // len(b)=0, cap(b)=5
    
  • range
    var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
    for i, v := range pow { ...
    for _, v := range pow { ...
    for i := range pow { ...
    
  • map
m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
    111, 222,
}

// literal
var m = map[string]Vertex{
	"Bell Labs": Vertex{ 1, 2 },
	"Google": Vertex{ 8, 9 },     // or "Google": { 8, 9 }
}

// manipulation
m[key] = elem
elem = m[key]
delete(m, key)
elem, ok = m[key]
  • function is also value
hypot := func(x, y float64) float64 {
		return math.Sqrt(x*x + y*y)
}
fmt.Println(hypot(3, 4))
  • function closure : function 裡頭自帶初始化後的實例
func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

pos, neg := adder(), adder()
for i := 0; i < 10; i++ {
    fmt.Println(pos(i), neg(-2*i))
}

Method

  • Method: Go 沒有類。然而可在結構類型上定義方法。
  • Method: 可以對包中的 任意 類型定義任意方法,而不僅是結構體。
  • Method: 不能對來自其他包的類型或基礎類型定義方法。
type Vertex struct { ... }

func (v *Vertex) Abs() float64 { ... }

func main() {
	v := &Vertex{3, 4}
	fmt.Println(v.Abs())
}
  • Interface :
type Abser interface {
	Abs() float64
}

func (v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

var a Abser
v := Vertex{3, 4}
a = &v // a *Vertex implements Abser
  • error
type error interface {
    Error() string
}

Concurrency

  • goroutine
go f(x, y, z)
  • channel
ch := make(chan int)
ch <- v
v := <-ch
// 緩衝 100
ch := make(chan int, 100)

// 關閉後,狀態就 ok == false
close(ch)
v, ok := <-ch
  • select : 在多個channel上等待, 知道某個可執行,隨機挑選一個可執行的。default 用於非阻塞。
var c, quit chan int

select {
    case c <- x:
        x, y = y, x+y
    case <-quit:
        fmt.Println("quit")
        return
    default:
        ...
}