[TOC]
闲言
最近需要看Kubernetes
(简写为k8s
)和docker
相关的技术资料,顺带学一下Go语言。
尝试了通过minikube部署遇到镜像下载和网络配置等等各种问题。
虽然k8s
很火热,但是资料其实很少,并且国内热衷于在其上做集成或者重新造轮子,对于这些用Go
实现的工具内部分析讨论不多。
所以趁着最近有点时间,边看minikube
源码边读 《The Go Programming Language》,将minikube
的架构、主要流程和实现做一个分析,Go
语言应该也能够学以致用,同时附带一下k8s
和docker
相关知识,以及八卦。
纸上得来终觉浅 绝知此事要躬行
项目 | 版本 |
---|---|
go | v1.8.3 |
minikube | v0.20.0 |
kubectl | v1.7.0 |
Go语言简介
Go是一门开源的编程语言,致力于开发简单、可靠和高效的软件。
Go语言始于2007年9月Google的三个工程师Robert Griesemer,Rob Pike,Ken Thompson,2009年11月正式宣布。
Go项目包括语言、工具和标准库,以及一切从简的理念。
作为较新的高层语言,Go有其后发优势:它包含了垃圾收集、包管理系统、函数式代码,语义作用域,系统调用接口和基于UTF-8
的常量字符串。
但是Go仅仅有相对较少的特性并且不太可能添加更多功能支持。
比如说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
0 - Go语言设计体系
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,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]
参考材料:
1 - 基础结构
++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,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) }
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",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() }原文链接:https://www.f2er.com/go/188291.html