Go學習筆記

1. byte與rune 字元串

byte 佔用1個位元組,8個bit,範圍為0->255(uint8)
rune 佔用4個位元組,32個bit,範圍為0-2^32(int32)(字符集大,中文必須使用這個)

func main() {
    var a byte = 'A'
    var b rune = 'B'
    fmt.Printf("a 佔用 %d 個位元組數\nb 佔用 %d 個位元組數", unsafe.Sizeof(a), unsafe.Sizeof(b))
}
//1 4

字元串
一個英文字元佔1個位元組,一個中文字元佔3個位元組

//表示 \r\n 這個字元串
//解釋型表示法
var str string = "\\r\\n"
//原生型表示法(不會根據轉義字元解析)
var str string = `\r\n`
//使用%q還原原生型表示法
fmt.Printf("的解釋型字元串是: %q", str)

2. go指針

創建方法

  • 定義變數取記憶體地址
a:=1
p=&a
  • 創建指針分配記憶體後,再給指針指向的記憶體寫入值
str:=new(string)
*str="test"
  • 聲明指針變數,從其他變數取地址並賦值
a:=1
var b *int
b=&a

& 在普通變數中取記憶體地址
* 該符號在賦值操作符的右邊時,表示在指針變數在取得變數值,在左邊是,是指指針指向的變數
列印記憶體地址

fmt.Printf("%p", p)
fmt.Println(p)

指針具有類型,比如string,int,*float64
指針的零值為nil
指針和切片都是引用類型,改變一個數組的值時,有兩個方法:

  • 傳入數組切片(推薦使用)
func modify(nums []int) {
    nums[0] = 90
}
func main() {
    nums := [3]int{89, 90, 91}
    modify(nums[:])
}
  • 傳入數組指針
func modify(nums *[3]int) {
    (*nums)[0] = 90
}

func main() {
    nums := [3]int{89, 90, 91}
    modify(&nums)
}

3. select用法

func main() {
    c1 := make(chan string, 1)
    c2 := make(chan string, 1)
    timeout := make(chan bool, 1)

    go makeTimeout(timeout, 2)

    select {
    case msg1 := <-c1:
        fmt.Println("c1 received: ", msg1)
    case msg2 := <-c2:
        fmt.Println("c2 received: ", msg2)
    case <-timeout:
        fmt.Println("Timeout, exit.")
    }
}
//一直阻塞,導致超時
  1. select 只能用於 channel 的操作(寫入/讀出/關閉),而 switch 則更通用一些;
  2. select 的 case 是隨機的,而 switch 里的 case 是順序執行;
  3. select 要注意避免出現死鎖,同時也可以自行實現超時機制;
  4. select 里沒有類似 switch 里的 fallthrough 的用法;
  5. select 不能像 switch 一樣接函數或其他表達式。

4. go異常機制

觸發panic

panic("crash")

recover(),捕獲panic資訊並列印

defer func() {
        // recover() 可以將捕獲到的panic資訊列印
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()

即使 panic 會導致整個程式退出,但在退出前,若有 defer 延遲函數,還是得執行完 defer 。
defer 在多個協程之間是沒有效果,在子協程里觸發 panic,只能觸發自己協程內的 defer,而不能調用 main 協程里的 defer 函數的。
panic:拋出異常,使程式崩潰
recover:捕獲異常,恢復程式或做收尾工作

5. 結構體

結構體可以繼承

type Person struct {
    Name string
}
type Man struct {
    person
    age string
}

結構體中,屬性名大寫為Public,小寫為Private
實例化方法:

  • 正常實例化
p:=Person{name:"xxx"}
  • 使用new
p:=new(Person)
p.name="xxx"
  • 使用&
var p *Person=&Person{}
p.name="xxx"
//等同於(*p).name="xxx"

從一個結構體實例對象中獲取欄位的值,通常都是使用 . 這個操作符,該操作符叫做 選擇器。
可以直接省去 * 取值的操作,選擇器 . 會直接解引用

Tags: