深入淺出 Gp - O'REILLY 心得
繼Introducing Go - O'REILLY之後的第二本Go的學習書藉,會再次記錄我認為需要記下的地方。
Package
package main
:特殊的套件,使用這個套件的目地通常代表程式碼需要被直接執行。import "reflect"
-> 其中有TypeOf可以用。
指令
gofmt file
:gofmt可以自動排版Golang的程式碼。 go build
:編譯成執行檔 go run
:編譯加執行 go fmt
:格式化程式碼成為Go標準格式 go version
:顯示Go版本
規則
大寫起頭=> public 小寫起頭=> private
習慣
三段落的程式排列方式 (像Python)
- 套件子句
- 任何 import 陳述句
- 主要的程式碼 自訂套件註解必須是以Package開頭 自訂套件函式的註解必須以函數名開頭 套件名稱應該都是小寫,理想上只有一個單字組成
變數名稱小寫駝峰 定義型別的方法時接收器參數通常以型別的第一個小寫英文字來命名 ex: func (m MyType) sayHi() {...}
因為型別是MyType所以參數是m 在為type struct設計getter與setter的時候有個命名慣例,假如參數是year,那寫入值會是SetYear,讀取值會是Year (省略Get)
用法
型態轉換 float64(var)
=> 把變數轉成float64這個型態
套件
log 日誌
log.Fatal(...)
=> 在console報錯並印出...
strconv 轉換字串類型
strings 字串處理
os 讀寫系統資料
file, err := os.Open("filePath") //讀文件
scanner := bufio.NewScanner(file) // 建立Buff暫存
for scanner.Scan() { // 讀一行
...
}
err = file.Close() // 關閉檔案釋放資源
nte/http
response, err := http.Get("url") // Get請求, response是含有Body結構,表示內容
defer response.Body.Close() // 釋放資源
body, err := ioutil.ReadAll(response.Body) // 用io把Body讀取出來
fmt.Println(string(body))
透過http.HandleFunc("/index", Foofunc)
的方式來把request請求導向到指 Foofunc有兩個參數
- writer http.ResponseWriter // 返回值給呼叫端
- request *http.Request // 接收來自呼叫端的值
request.FromValue("key")
定的函式 透過err := http.ListenAndServe("ip:port", nil)
來監聽呼叫http.Redirect(writer, request, "/anotherpage", http.StatusFound)
重導向
errors
errors提供了error來做回報錯誤的方法
func foo() error {
return errors.New("invalid vale") // 作為回傳錯誤
return nil // 作為正常
}
error其實是一個具有Error()方法的介面
html/template (相似於text/template)
html, err := template.ParseFiles("view.html")
err = html.Execute(writer, data) // 此處writer是http.ResponseWriter
介面
斷言 => 從介面還原成類型的方法
interfaceVar.(typeA) // 斷言此interfaceVar是typeA,斷言後可以使用typeA自己的方法
goroutines 併發 (concurrency)
go foo()
另開一個類似執行續的方式(goroutines)執行foo()
- 注意子程序可以比主程序(main)還晚完成,導致主程序關閉時關閉所有子程序
x := go foo()
無法這樣使用,因為是另開一個goroutines執行,所以Go會阻止你,若想要拿到goroutines的回傳值,你應該嘗試channel
channel 通道
channel可以處理不同goroutines之間的資料傳遞,關鍵詞是chan
並放在類型前面
var myChannel chan float64
myChannel = make(chan float64)
// or ----
myChannel := make(chan float64)
透過傳遞channel,我們就可以使用<-
來傳遞資料
func foo(str chan string) {
str <- "abc" // 放值到str
}
func main() {
strChan := make(chan string)
go foo(strChan)
str := <-strChan // 從strChan取值
fmt.Println(str)
}
<-
會阻塞通道,也就是等待資料被提取
func foo(str chan string) {
str <- "abc" // 執行到這行,foo會停住,等待str通道的另一端接收資訊之後才往下執行
str <- "cde"
}
func main() {
strChan := make(chan string)
go foo(strChan)
str := <-strChan // 讀取strChan通道的值,讀取之後才會往下執行
fmt.Println(str) // abc
str = <-strChan
fmt.Println(str) // cde
}
可以為通道增加緩衝,這樣就不會因為一筆資料而堵塞
函示
Go像JavaScript一樣,可以把func視為一個變數,並傳遞使用 也可以直接宣告函式var foo func(int, int)string
,這樣在做foo = SomeFunc
的時候可以防止函式的參數與回傳值不對
知識
for range 對map做迴圈讀取時的順序不是固定的。(map不是有序的) main()其實也是由goroutines執行的
測試
- 檔名為原檔名加上_test ex:
a_test.go
- 測試的package可以與原package不同,但若要存取原packgae私有的資料那就必須在相同的package下
- 使用原生套件
testing
- 測試函數名需要以Test作為前墜
- 測試函數需要一個指向testing.T的指標作為參數
- 用
t.Error
與t.Errorf
來表示出錯 - 通過
go test
命令來執行測試,可以加上-run Na
的方式只執行所有測試函示包含Na的測試
留言
張貼留言