[TOC]linux
最近須要看Kubernetes
(簡寫爲k8s
)和docker
相關的技術資料,順帶學一下Go語言。golang
嘗試了經過minikube部署遇到鏡像下載和網絡配置等等各類問題。
雖然k8s
很火熱,可是資料其實不多,而且國內熱衷於在其上作集成或者從新造輪子,對於這些用Go
實現的工具內部分析討論很少。docker
因此趁着最近有點時間,邊看minikube
源碼邊讀 《The Go Programming Language》,將minikube
的架構、主要流程和實現作一個分析,Go
語言應該也可以學以至用,同時附帶一下k8s
和docker
相關知識,以及八卦。編程
紙上得來終覺淺 絕知此事要躬行
項目 | 版本 |
---|---|
go | v1.8.3 |
minikube | v0.20.0 |
kubectl | v1.7.0 |
Go是一門開源的編程語言,致力於開發簡單、可靠和高效的軟件。
canvas
Go語言始於2007年9月Google的三個工程師Robert Griesemer, Rob Pike, Ken Thompson,2009年11月正式宣佈。api
Go項目包括語言、工具和標準庫,以及一切從簡的理念。數組
做爲較新的高層語言,Go有其後發優點:它包含了垃圾收集、包管理系統、函數式代碼,語義做用域,系統調用接口和基於UTF-8
的常量字符串。服務器
可是Go僅僅有相對較少的特性而且不太可能添加更多功能支持。
好比說Go沒有隱式數字轉換,沒有構造和析構函數,沒有操做符重載,沒有默認參數,沒有繼承,沒有泛型,沒有異常,沒有宏,沒有函數標註,也沒有線程本地存儲。網絡
Go語言自己成熟且穩定,而且保證向下兼容。架構
https://golang.org/doc/install
# 刪除系統已經安裝的golang sudo apt remove golang-go # 下載最新版本 wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz # 解壓到/usr/local/go下 sudo tar -C /usr/local -zxvf go1.8.3.linux-amd64.tar.gz # 把go/bin加入到用戶PATH環境變量,或是系統範圍 /etc/profile echo "PATH=$PATH:/usr/local/go/bin" >> $HOME/.profile
查看安裝的Go版本:
$ source ~/.profile $ go version go version go1.8.3 linux/amd64
graph TD CSP[CSP, Hoare, 1978]-->Squeak Squeak[Squeak, Cardelli & Pike, 1985]-->Newsqueak Newsqueak[Newsqueak, Pike, 1989]-->Alef Alef[Alef, Winterbottom, 1992]-->Go ALGOL-60[ALGOL 60, Bakus etal., 1960]-->Pascal Pascal[Pascal, Wirth, 1970]-->Modula-2 Modula-2[Modula-2, Wirth, 1980]-->Oberon Oberon[Oberon, Wirth & Gutknecht, 1986]-->Oberon-2 Oberon-->Object-Oberon Object-Oberon[Object Oberon, Mossenbock, Templ & Griesemer, 1990]-->Oberon-2 Oberon-2[Oberon-2, Wirth & Mossenbock, 11991]-->Go ALGOL-60-->C[C, Ritchie, 1972] C-->Go[Go, Griesemer, Pike & Thompson, 2009]
參考材料:
go run
能夠直接運行go代碼文件
go build
編譯代碼
go fmt
幫助格式化代碼
++helloworld.go++ (打印字符串)
// Go代碼按包組織,相似其它語言的模塊或庫 // 當前Go有100多個包,涵蓋了輸入輸出,排序,文本處理等基本任務 package main // main包表示這是可執行文件而不是庫代碼 import "fmt" // fmt包負責處理格式化輸入輸出 // 函數聲明是func關鍵字 func main() { // { 必需要跟代碼在同一行,不能單獨一行 fmt.Println("Hello,世界!") // 默認不用寫分號,Go會自動加上 } // Go默認採用UTF-8編碼,兼容多種語言
++echo.go++ (回顯命令參數)
package main import ( // 導入多個包的經常使用形式 "fmt" "os" ) func main() { var sep = "" // Go不容許聲明沒有用到的變量 // range關鍵字,數組切分跟Python相似,無需括號 for _, arg := range os.Args[1:] { // := 是聲明變量的簡寫 sep += arg + " " // 支持逆波蘭表達式,僅支持i++形式,不支持++i } fmt.Println(sep) }
++dup.go++ (統計重複行數)
package main import ( // 導入多個包的經常使用形式 "bufio" "fmt" "os" ) func main() { counts := make(map[string]int) // 內置函數make建立一個新的map類型變量 if len(os.Args) > 1 { for _, file := range os.Args[1:] { // 若是有參數則做爲文件打開 f, err := os.Open(file) if err != nil { // 錯誤值 fmt.Fprintf(os.Stderr, "dup: %v\n", err) continue } else { countLines(f, counts) f.Close() } } } else { countLines(os.Stdin, counts) } for line, num := range counts { if num > 1 { // 不須要`(`,但`{`仍是要有 fmt.Printf("> %d\t'%s'\n", num, line) // 與C語言的printf相似 } } } // 聲明函數參數的形式,counts是引用類型 func countLines(f *os.File, counts map[string]int) { for input := bufio.NewScanner(f); input.Scan(); { // for能夠替代while counts[input.Text()]++ } }
++gif.go++ (生成gif動態圖)
package main // 演示Go的標準圖像包 import ( "image" "image/color" // 引用包的最後一部分,如color.White "image/gif" "io" "math" "math/rand" "os" ) // 一種緊湊的方式聲明覆合類型,詳見第四部分 var palette = []color.Color{color.White, color.Black} // slice // 聲明常量,至關於給一些值起個名字 const ( // 常量只能是數字、字符串或bool值 white = 0 // first color in palette black = 1 // next color in palette ) func main() { lissajous(os.Stdout) } func lissajous(out io.Writer) { const ( cycles = 5 // number of complete x oscillator revolutions res = 0.001 // angular resolution size = 100 // image canvas covers [-size..+size] nframes = 64 // number of animation frames delay = 8 // delay between frames in 10ms units ) freq := rand.Float64() * 3.0 // relative frequency of y oscillator anim := gif.GIF{LoopCount: nframes} // struct phase := 0.0 // phase difference for i := 0; i < nframes; i++ { rect := image.Rect(0, 0, 2*size+1, 2*size+1) img := image.NewPaletted(rect, palette) for t := 0.0; t < cycles*2*math.Pi; t += res { x := math.Sin(t) y := math.Sin(t*freq + phase) img.SetColorIndex(size+int(x*size+.5), size+int(y*size+.5), black) } phase += .1 anim.Delay = append(anim.Delay, delay) anim.Image = append(anim.Image, img) } gif.EncodeAll(out, &anim) }
++fetch.go++ (並行獲取URL內容)
package main // main包表示這是可執行文件而不是庫代碼 import ( "fmt" "io" "io/ioutil" "net/http" "os" "time" ) func main() { // main函數運行運行於一個goroutine內 start := time.Now() ch := make(chan string) // channel是在goroutine間消息通訊的機制 for _, url := range os.Args[1:] { go fetch(url, ch) // goroutine是並行執行的函數,go語句創建goroutine } for range os.Args[1:] { fmt.Println(<-ch) // 消息傳遞是阻塞式的 } fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds()) } func fetch(url string, ch chan<- string) { start := time.Now() resp, err := http.Get(url) if err != nil { ch <- fmt.Sprint(err) return } nb, err := io.Copy(ioutil.Discard, resp.Body) resp.Body.Close() if err != nil { ch <- fmt.Sprintf("while reading %s: %v\n", url, err) return } secs := time.Since(start).Seconds() ch <- fmt.Sprintf("%.2fs, %7d, %s", secs, nb, url) }
++server.go++ (Web服務器示例)
package main import ( "fmt" "log" "net/http" "sync" ) var mu sync.Mutex var count int func main() { http.HandleFunc("/", handler) http.HandleFunc("/counter", counter) log.Fatal(http.ListenAndServe("localhost:8000", nil)) } func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto) for k, v := range r.Header { fmt.Fprintf(w, "Header[%s] = %q\n", k, v) } fmt.Fprintf(w, "Host = %q\n", r.Host) fmt.Fprintf(w, "RemoteAddr = %q\n", r.RemoteAddr) if err := r.ParseForm(); err != nil { log.Print(err) } for k, v := range r.Form { fmt.Fprintf(w, "Form[%q] = %q\n", k, v) } mu.Lock() count++ mu.Unlock() fmt.Fprintf(w, "URL.path = %q\n", r.URL.Path) } func counter(w http.ResponseWriter, r *http.Request) { mu.Lock() fmt.Fprintf(w, "Count: %d\n", count) mu.Unlock() }
switch
語句與C語言相似,但沒有fall through特性(有fallthrough
語句)
命名類型,相似C語言的結構體
指針,相似C語言,支持*
和&
操做符,但不支持指針運算
方法是命名類型裏的函數函數,與C++的類函數類似
接口是聲明瞭相同方法的抽象類型
go doc http.file
能夠查看包的幫助信息
註釋支持/* ... */
和//
兩種方式