defer 關鍵字
以下是一個簡單的小 demo
package main
import "fmt"
func main() {
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
panic("error!")
}
// 3
// 2
// 1
// panic:error!
程式遇到 panic 時,會先依次執行 defer 然後再將 panic 傳遞出去。
for 迴圈中的臨時變數
還是以一個小 demo 來練習
package main
import "fmt"
type student struct {
Name string
Age int
}
func initStudents() map[string]*student {
m := make(map[string]*student)
students := []student{
{Name: "jack", Age: 24},
{Name: "rose", Age: 23},
{Name: "wang", Age: 22},
}
for _, student := range students {
m[student.Name] = &student
}
return m
}
func main() {
students := initStudents()
for k, v := range students {
fmt.Println(k, *v)
}
}
// rose {wang 22}
// wang {wang 22}
// jack {wang 22}
for 迴圈遍歷時,student 是一個臨時變數,遍歷過程中,在記憶體中的地址不變,賦值都是指向了同一個記憶體區域,導致後面的值其實都是一樣的。
在 goroutine 中列印
package main
import (
"fmt"
"sync"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(5)
for i := 0; i < 5; i++ {
go func() {
fmt.Println("i: ", i)
wg.Done()
}()
}
wg.Wait()
}
// 5
// 5
// 5
// 5
// 5
在 go 關鍵字後建立了一個匿名函式,同時它也是一個閉包,程式碼塊中的 i 是對外部變數 i 的引用,go 關鍵字開啟 goroutine 執行閉包,意味著它不會順序執行,一般等該程式碼片段被排程器執行的時候,for 迴圈已經退出,此時 i 為 5,所以會在控制檯列印出 5 個 5。
結構體組合
package main
import "fmt"
type People struct{}
func (p *People) ShowA() {
fmt.Println("showA")
p.ShowB()
}
func (p *People) ShowB() {
fmt.Println("showB")
}
type Teacher struct {
People
}
func (t *Teacher) ShowB() {
fmt.Println("teacher showB")
}
func main() {
t := Teacher{}
t.ShowA()
t.ShowB()
}
// showA
// showB
// teacher showB
go 中沒有繼承,只有組合,Teacher 中的 People 是一個匿名物件,通過它呼叫的函式都是自身的。