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.")
}
}
//一直阻塞,導致超時
- select 只能用於 channel 的操作(寫入/讀出/關閉),而 switch 則更通用一些;
- select 的 case 是隨機的,而 switch 里的 case 是順序執行;
- select 要注意避免出現死鎖,同時也可以自行實現超時機制;
- select 里沒有類似 switch 里的 fallthrough 的用法;
- 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"
從一個結構體實例對象中獲取欄位的值,通常都是使用 . 這個操作符,該操作符叫做 選擇器。
可以直接省去 * 取值的操作,選擇器 . 會直接解引用