前言
TIDB K8S 由GO 語(yǔ)言編寫;mysql 和 mongodb 由c++編寫
go 沒(méi)有構(gòu)造和析構(gòu),沒(méi)有運(yùn)算符重載叠洗,沒(méi)有形參默認(rèn)值凫海,沒(méi)有繼承呛凶,沒(méi)有泛型
go 原生支持 Unicode,可以處理所有國(guó)家的語(yǔ)言
{ 符號(hào)必須和關(guān)鍵字 func 在同一行
gofmt 保存的時(shí)候自動(dòng)格式化go代碼
goimports 保存的時(shí)候自動(dòng)導(dǎo)入包
gometalinter 保存的時(shí)候自動(dòng)檢查go 語(yǔ)法
for 循環(huán)的三種形式:
for 初始化條件;條件(布爾值)行贪;循環(huán)體之后被執(zhí)行的表達(dá)式 {
}
for 條件(布爾值){
// 傳統(tǒng)的while 循環(huán)
}
for _,arg := range os.Args[1:]{
}
Printf 各種參數(shù)解釋:
%d 十進(jìn)制 %x 十六進(jìn)制 %o 八進(jìn)制 %b 二進(jìn)制 %f/%g 浮點(diǎn)數(shù) %t 布爾型
%c 字符(unicode碼點(diǎn)) %s 字符串 %q 帶引號(hào)字符串 %v 內(nèi)置格式任何值
%T 任何值的類型 %% 百分號(hào)本身
聲明的作用域是在程序文本中出現(xiàn)的區(qū)域漾稀,是一個(gè)編譯屬性
變量的生命周期是變量在程序執(zhí)行時(shí)被程序其它部分所引用的起止時(shí)間,是一個(gè)運(yùn)行屬性建瘫。匿名函數(shù)就是生命周期大于作用域的是例子
基本數(shù)據(jù)類型
四大類:基礎(chǔ)類型崭捍;聚合類型(數(shù)組和結(jié)構(gòu)體,slice,map);引用類型(指針啰脚,slice,map,函數(shù)殷蛇,channel);接口類型
rune = int32 byte = uint8 uintptr 無(wú)符號(hào)整數(shù)橄浓,大小不明確粒梦,用于存放指針
字符串是不可變的字節(jié)序列,不能修改
常量是一種表達(dá)式荸实,必須在編譯階段就能計(jì)算出值
常量生成器iota 從0開(kāi)始逐步加1
數(shù)組的定義方式 var a [3]int = [3]int{1,2,3} q := […]int{1,2,3}
[3]int 和 [4]int 并不是同一個(gè)類型
slice 通常寫成 []T ,看上去像是沒(méi)有長(zhǎng)度的數(shù)組類型
map是go語(yǔ)言中散列表的引用匀们。 ages := make(map[string]int)
函數(shù)
func name(parameter-list) (result-list){
body
}
方法
方法的聲明和普通函數(shù)的聲明類似,只是函數(shù)名字前面多了一個(gè)參數(shù)准给,將方法綁在參數(shù)對(duì)應(yīng)的類型上
func (p Point) name(parameter-list) (result-list){
// 將方法綁在Point類型上
}
go 語(yǔ)言中沒(méi)有this 和 self
go 和許多其他面向?qū)ο笳Z(yǔ)言不同泄朴,它可以將方法綁定在任何類型上
同一個(gè)包下的任何類型都可以聲明方法,只要它的類型既不是指針類型也不是接口類型
由于主調(diào)函數(shù)會(huì)復(fù)制每一個(gè)實(shí)參變量露氮,如果一個(gè)函數(shù)需要更新一個(gè)變量祖灰,或者一個(gè)實(shí)參太大,我們想避免復(fù)制整個(gè)實(shí)參畔规,因此需要使用使用指針傳遞變量的地址
指針接收著合法的三種情況:
形參接收者和實(shí)參接收者是同一類型局扶。比如都是T類型或T類型;
實(shí)參接收者是T類型油讯,形參接收者是T類型详民。編譯器或隱式獲取變量的地址;
實(shí)參接收者是*T類型陌兑,形參接受者是T類型沈跨。編譯器隱式解引用接收者,獲取實(shí)際的值
接口
接口中只包含0個(gè)或多個(gè)方法簽名兔综,不包含具體實(shí)現(xiàn)
實(shí)現(xiàn)接口不需要顯示聲明饿凛,只需要實(shí)現(xiàn)相應(yīng)方法即可
type Namer interface {
method1(param_list) return_list
}
接口的名字最好是以 er , r , able 結(jié)尾
空接口是指沒(méi)有定義任何方法的接口狞玛。空接口類型的變量可以存儲(chǔ)任意類型的變量
類型的斷言 x.(T) x 表示類型為interface{}的變量
T 表示斷言x可能是的類型 true表示斷言成功 false 表示斷言失敗
協(xié)程和通道
通常一個(gè)進(jìn)程里啟動(dòng)上萬(wàn)個(gè)線程涧窒,系統(tǒng)就不堪重負(fù)心肪。go 可以輕松開(kāi)啟百萬(wàn)協(xié)程
通道是并發(fā)安全的數(shù)據(jù)結(jié)構(gòu),類似于內(nèi)存消息隊(duì)列纠吴,允許很多協(xié)程并發(fā)對(duì)通道進(jìn)行讀寫
main函數(shù)運(yùn)行在主協(xié)程里硬鞍。go 語(yǔ)言里只有一個(gè)主協(xié)程,其余都是子協(xié)程戴已,子協(xié)程是平行關(guān)系
主協(xié)程運(yùn)行結(jié)束固该,其它協(xié)程就會(huì)立即消亡,不管它們是否已經(jīng)開(kāi)始運(yùn)行
子協(xié)程異常退出會(huì)傳播到主協(xié)程糖儡,導(dǎo)致主協(xié)程也會(huì)掛掉
var chan1 chan string
chan2 = make(chan string)
單向channel var chan3 chan <- int chan3 := make(chan <- int)
for range 可以讀取 chan 中的值
操作值為nil的channel ||| 被關(guān)閉的channel ||| 正常的 channel
close : panic panic 成功關(guān)閉
c<- : 永遠(yuǎn)阻塞 panic 阻塞或成功發(fā)送
<-c :永遠(yuǎn)阻塞 永遠(yuǎn)不阻塞 阻塞或成功接收
錯(cuò)誤和異常
fmt.Errorf 和 errors.New("something happened ") 自定義一個(gè)錯(cuò)誤
panic 和 recover 處理異常伐坏,然后升級(jí)為錯(cuò)誤返回給系統(tǒng)
使用共享變量實(shí)現(xiàn)并發(fā)(即傳統(tǒng)的同步機(jī)制)
type a struct {
a int
lock sync.Mutex
}
每個(gè)OS線程有一個(gè)固定大小的棧內(nèi)存,一般為2MB左右
協(xié)程的棧不是固定大小的握联,典型情況下為2kb 桦沉,最大限制達(dá)到1GB
OS線程由OS內(nèi)核調(diào)度,每隔幾毫秒金闽,一個(gè)硬件中斷發(fā)給CPU,CPU調(diào)用一個(gè)調(diào)度器的函數(shù)纯露,這個(gè)函數(shù)暫停正在運(yùn)行的線程,將寄存器信息保存在內(nèi)存
go 協(xié)程有自己的調(diào)度器呐矾,于內(nèi)核調(diào)度器類似苔埋,但不是由硬件時(shí)鐘觸發(fā)懦砂,而是go 語(yǔ)言內(nèi)部結(jié)構(gòu)觸發(fā)蜒犯,不需要切換至內(nèi)核環(huán)境
GOMAXPROCS 是m:n 模型中的n
休眠和正在被通道阻塞的gorutine不占用線程
阻塞在I/O 和 其它系統(tǒng)中或調(diào)用非go寫的函數(shù),gorutine需要一個(gè)單獨(dú)的os線程荞膘,但這個(gè)線程不計(jì)算在GOMAXPROCS中
普通線程有獨(dú)特的標(biāo)識(shí)罚随;gorutine 沒(méi)有標(biāo)識(shí)
包 和 go工具
go 自帶100多個(gè)包 go社區(qū)的包可以在http://godoc.org中找到
go 編譯比其它語(yǔ)言快,主要有三個(gè)原因
所有的導(dǎo)入都必須在每一個(gè)源文件的開(kāi)頭顯示列出羽资;
包的依賴性形成有向無(wú)環(huán)圖淘菩,因?yàn)闆](méi)有環(huán),所以包可以獨(dú)立編譯屠升;
包編譯輸出的目標(biāo)文件不僅記錄自己的導(dǎo)出信息潮改,還記錄所依賴包的導(dǎo)出信息。編譯包時(shí)腹暖,編譯器必須從每一個(gè)導(dǎo)入讀取目標(biāo)文件汇在,但不會(huì)超過(guò)這些文件
import (
"fmt"
"os"
)
import (
crypto/rand
mrand ***/rand //避免沖突
)
import (
_ "img" //空導(dǎo)入
)
import (
"geometry/rectangle"
)
var _ = rectangle.Area // 錯(cuò)誤屏蔽器
func main() {
}
import (
_ "geometry/rectangle" //調(diào)用了rectangle 包的Init函數(shù),不需要在代碼中使用
)
func main() {
}
包名一般使用簡(jiǎn)短的名字
go env 查看環(huán)境配置
大部分用戶必須進(jìn)行的唯一的配置是 GOPATH環(huán)境變量
GOROOT:GO發(fā)行版的根目錄脏答,用戶無(wú)需設(shè)置GOROOT
go get -u 獲取每個(gè)包的最新版本
go build / go build . : 意味著對(duì)當(dāng)前目錄進(jìn)行編譯
GOARCH 處理器的架構(gòu) GOOS 目標(biāo)操作系統(tǒng)
go build 的作用:
用于測(cè)試編譯多個(gè)包或一個(gè)main包糕殉;
build 命令編譯包丟棄非main包編譯結(jié)果亩鬼,只是檢查是否能夠被編譯;
保留main包的編譯結(jié)果阿蝶;
/bin 存放編譯后的可執(zhí)行文件 /pkg 存放編譯后的包文件
package main
import (
"fmt"
"cal" //到入自定義的包雳锋,cal必須在src文件下,必須和main同一級(jí)
)
func main() {
fmt.Println("hello word")
fmt.Println("相加",cal.Add(10,20))
fmt.Println("相減",cal.Subtraction(40,50))
}
普通包【非main包】
go build add.go 【編譯add.go,不生成exe執(zhí)行文件】
go build -o add.exe add.go 【指定生成exe執(zhí)行文件羡洁,但不能運(yùn)行此文件玷过,不是main包】
main包
go build main.go 【生成exe執(zhí)行文件】
go build -o main.exe main.go 【指定生成main.exe可執(zhí)行文件】
如果是main包,當(dāng)你執(zhí)行g(shù)o build 之后筑煮,會(huì)在當(dāng)前目錄生成一個(gè)可執(zhí)行文件.exe冶匹。
如果需要再$GOPATH/bin下生成相應(yīng)的文件,需要執(zhí)行g(shù)o install 或 go build -o 路徑/ XXX.exe XXX.go
項(xiàng)目文件夾下有多個(gè)文件
go build 【編譯當(dāng)前目錄下所有的go 文件】
go build add.go delete.go 【編譯add.go 和 delete.go】
go build 會(huì)忽略目錄下以 _ 或 . 開(kāi)頭的文件
go test
文件名以 _test.go 結(jié)尾
test 測(cè)試的方法名以 Test 打頭咆瘟,形參為(t * testing.T),檢查程序的邏輯是否正確
benchmark(基準(zhǔn))測(cè)試以 Benchmark 打頭嚼隘,形參為(t * testing.T),衡量函數(shù)的性能
example測(cè)試的方法以 Example 打頭,形參為(t * testing.T ),提供一個(gè)由編譯器保證正確的文檔
go test -v hello_test.go 測(cè)試整個(gè)文件
go test -v hello_test.go -test.run TestHello 測(cè)試單個(gè)函數(shù)
go run
用于對(duì)命令源碼文件做編譯+鏈接操作 操作產(chǎn)生臨時(shí)可執(zhí)行程序并執(zhí)行袒餐,一般用于調(diào)試程序
go install
用于 構(gòu)建 + 安裝包
對(duì) 庫(kù)源碼文件 go install ,直接編譯整個(gè)包飞蛹,會(huì)個(gè)pkg目錄下生成.a靜態(tài)文件,供其他包調(diào)用
對(duì) 命令源碼文件 go install ,編譯+鏈接+生產(chǎn)可執(zhí)行文件灸眼,會(huì)在/bin目錄下生成可執(zhí)行文件
go build 和 go run 后面加**.go文件 go install 后面直接加xxx目錄名