Go語言從入門到實(shí)戰(zhàn)

一、Go語言背景和發(fā)展

1.軟件開發(fā)的新挑戰(zhàn)

  • 多核硬件架構(gòu)
  • 超大規(guī)模分布式計(jì)算集群
  • Web模式導(dǎo)致的前所未有的開發(fā)規(guī)模和更新速度

2.Go的三位創(chuàng)始人

  • Rob Pike:Unix的早期開發(fā)者,UTF-8創(chuàng)始人
  • Ken Thompson:Unix的創(chuàng)始人翠胰,C語言創(chuàng)始人,1983年獲圖靈獎(jiǎng)
  • Robert Griesemer:Google V8 JS Engine開發(fā)者竖慧,Hot Spot開發(fā)者

3.Go語言特點(diǎn)

  • 簡單:Go只有25個(gè)關(guān)鍵字飞主;特別是對(duì)于一些復(fù)雜編程任務(wù)如:并發(fā)編程,內(nèi)存管理前鹅,Go語言有內(nèi)置的并發(fā)支持及GC
  • 高效:Go是編譯的靜態(tài)類型語言摘悴,并且可以通過指針進(jìn)行直接內(nèi)存訪問
  • 生產(chǎn)力:簡單清新的依賴管理,簡單清新的語法舰绘,以及獨(dú)特的接口類型

二蹂喻、第一個(gè)Go程序

[圖片上傳失敗...(image-8dd3db-1556979504914)]

1.應(yīng)用程序入口

  • 必須是main包
  • package main
  • 必須是main方法
  • func main()
  • 文件名不一定是main.go

2.退出返回值

  • Go中main函數(shù)不支持任何返回值
  • 通過os.Exit來返回狀態(tài)

3.獲取命令行參數(shù)

  • main函數(shù)不支持傳入?yún)?shù)
  • 在程序中直接通過os.Args獲取命令行參數(shù)

4.基本數(shù)據(jù)類型

  • bool
  • string
  • int int8 int16 int32 int64
  • uint uint8 uint16 uint32 uint64
  • byte // alias for uint8
  • rune
  • float32 float64
  • complex64 complex128

與其他主要編程的差異:

  1. Go語言不允許隱式類型轉(zhuǎn)換
  2. 別名和原有類型也不能進(jìn)行隱式類型轉(zhuǎn)換

類型的預(yù)定義值:

  1. math.MaxInt64
  2. math.MaxFloat64
  3. math.MaxUint32

指針類型

  1. 不支持指針運(yùn)算
  2. string是值類型,其默認(rèn)的初始值為空字符串除盏,而不是nil

5.運(yùn)算符

用 == 比較數(shù)組

  • 相同維數(shù)且含有相同個(gè)數(shù)元素的數(shù)組才可以比較
  • 每個(gè)元素都相同的才相等

按位清零運(yùn)算符

  • &^

6.循環(huán)

Go語言僅支持循環(huán)關(guān)鍵字for

for i := 0; i <= 9; I++

7.if條件

  1. condition表達(dá)式結(jié)果必須為布爾值
  2. 支持變量賦值:
if var declaration; condition {
    
}

8.switch條件

  1. 條件表達(dá)式不限制為常量或者整數(shù)
  2. 單個(gè)case中叉橱,可以出現(xiàn)多個(gè)結(jié)果選項(xiàng),使用逗號(hào)分隔
  3. 與C語言等規(guī)則相反者蠕,Go語言不需要用break來明確退出一個(gè)case
  4. 可以不設(shè)定switch之后的條件表達(dá)式,在此種情況下掐松,整個(gè)switch結(jié)構(gòu)與多個(gè)if...else...的邏輯作用等同
switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
        //break
    case "linux":
        fmt.Println("Linux.")
    default:
        fmt.Println("%s.",os)
}
switch {
    case 0 <= Num && Num <= 3:
        fmt.Printf("0-3")
    case 4 <= Num && Num <= 6:
        fmt.Printf("4-6")
}
switch I {
    case 0,2:
        fmt.Printf("0-2")
    case 1,3:
        fmt.Printf("1-3")
}

9.Map元素的訪問

在訪問的Key不存在時(shí)踱侣,仍會(huì)返回零值,不能通過返回nil來判斷元素是否存在

if v,ok := map1["key1"]; ok{
    
} else {
    
}

map的遍歷

for k,v := range map1{
    
}

10.Map與工廠模式

  • Map的value可以是一個(gè)方法
  • 與Go的Dock type接口方式一起大磺,可以方便的實(shí)現(xiàn)單一方法對(duì)象的工廠模式

11.實(shí)現(xiàn)Set

Go的內(nèi)置集合中沒有Set實(shí)現(xiàn)抡句,可以map[type]bool

  1. 元素的唯一性
  2. 基本操作
    1. 添加元素
    2. 判斷元素是否存在
    3. 刪除元素
    4. 元素個(gè)數(shù)

12.字符串

  1. string是數(shù)據(jù)類型,不是引用或指針類型
  2. string是只讀的byte slice杠愧,len函數(shù)可以它所包含的byte數(shù)
  3. string的byte數(shù)組可以存放任何數(shù)據(jù)

13.Unicode UTF8

  1. Unicode是一種字符集(code point)
  2. UTF8是unicode的存儲(chǔ)實(shí)現(xiàn)(轉(zhuǎn)換為字節(jié)序列的規(guī)則)

14.常用字符串函數(shù)

  1. strings包(https://golang.org/pkg/strings/
  2. strconv包(https://golang.org/pkg/strconv

15.函數(shù)是一等公民

  1. 可以有多個(gè)返回值
  2. 所有參數(shù)都是值傳遞:slice待榔、map、channel會(huì)有傳引用的錯(cuò)覺
  3. 函數(shù)可以作為變量的值
  4. 函數(shù)可以作為參數(shù)和返回值

16.Go接口

  1. 接口為非入侵性流济,實(shí)現(xiàn)不依賴接口定義
  2. 所以接口的定義可以包含在接口使用者包內(nèi)

17.空接口與斷言

  1. 空接口可以表示任何類型
  2. 通過斷言來將空接口轉(zhuǎn)換為制定類型
v, ok := p.(int) //ok=true時(shí)為轉(zhuǎn)換成功

18.Go接口最佳實(shí)踐

  1. 傾向于使用小的接口定義锐锣,很多接口只包含一個(gè)方法
type Reader interface {
    Read(p []byte) (n int, err error)
}
type Writer interface {
    Write(p []byte) (n int,err error)
}
  1. 較大的接口定義,可以由多個(gè)小接口定義組合而成
type ReadWriter interface {
    Reader
    Writer
}
  1. 只依賴于必要功能的最小接口
func StoreData(reader Reader) error {
    ......
}

19.編寫好的錯(cuò)誤處理

  1. 沒有異常機(jī)制
  2. error類型實(shí)現(xiàn)了error接口
type error interface {
    Error() string
}
  1. 可以通過errors.New來快速創(chuàng)建錯(cuò)誤實(shí)例
errors.New("")

20.panic

  • panic用于不可以恢復(fù)的錯(cuò)誤
  • panic退出前會(huì)執(zhí)行defer指定的內(nèi)容

panic vs os.Exit

  • os.Exit 退出時(shí)不會(huì)調(diào)用defer指定的函數(shù)
  • os.Exit 退出時(shí)不輸出當(dāng)前調(diào)用棧信息

recover

defer func() {
   if err := recover(); err != nil {
       //恢復(fù)錯(cuò)誤
   } 
}()

21.package

  1. 基本復(fù)用模塊單元
    1. 以首字母大寫來表明可被包外代碼訪問
  2. 代碼的package可以和所在的目錄不一致
  3. 同一目錄里的Go代碼的package要保持一致
  4. 通過go get來獲取遠(yuǎn)程依賴
    1. go get -u強(qiáng)制從網(wǎng)絡(luò)更新遠(yuǎn)程依賴
  5. 注意代碼在Github上的組織形式绳瘟,以適應(yīng)go get
    1. 直接以代碼路徑開始雕憔,不要有src

22.init方法

  • 在main被執(zhí)行前,所有依賴的package的init方法都會(huì)被執(zhí)行
  • 不同包的init函數(shù)按照包導(dǎo)入的依賴關(guān)系決定執(zhí)行順序
  • 每個(gè)包可以有多個(gè)init函數(shù)
  • 包的每個(gè)源文件也可以有多個(gè)init函數(shù)糖声,這點(diǎn)比較特殊

23.依賴管理

Go未解決的依賴問題

  1. 同一環(huán)境下斤彼,不同項(xiàng)目使用同一包的不同版本
  2. 無法管理對(duì)包的特定版本的依賴

vendor路徑
<p>隨著Go1.5 release 版本的發(fā)布分瘦,vendor目錄被添加到除了GOPATH和GOROOT之外的依賴目錄查找的解決方案。在Go 1.6之前琉苇,你需要手動(dòng)的設(shè)置環(huán)境變量</p>

查找依賴包路徑的解決方案如下:

  1. 當(dāng)前包下的vendor目錄
  2. 向上級(jí)目錄查找嘲玫,直到找到src下的vendor目錄
  3. 在GOPATH下面查找依賴包
  4. 在GOROOT目錄下查找

常用的依賴管理

三、并發(fā)機(jī)制

1.Thread vs. Groutine

  1. 創(chuàng)建時(shí)默認(rèn)的stack的大小
    1. JDK5以后Java Thread stack默認(rèn)為1M
    2. Groutine的Stack初始化大小為2K
  2. 和KSE (kernel Space Entity)的對(duì)應(yīng)關(guān)系
    1. Java Thread是1:1
    2. Groutine是M:N

2.Lock

package sync
    Mutex
    RWLock

WaiteGroup

3.CSP并發(fā)機(jī)制

CSP vs. Actor

  • 和Actor的直接通訊不同并扇,CSP模式則是通過Channel進(jìn)行通訊的去团,更松耦合一些
  • Go中channel是有容量限制并且獨(dú)立于處理Groutine,而如Erlang拜马,Actor模式中的mailbox容量是無限的渗勘,接受進(jìn)程也總是被動(dòng)處理消息

4.select

多渠道的選擇

select {
    case ret := <- retCh1:
        t.Logf("result %s", ret)
    case ret := <- retCh2:
        t.Logf("result %s", ret)
    default:
        t.Error("No one returned")
}

超時(shí)控制

select {
    case ret := <- retCh:
        t.Logf("result %s", ret)
    case <- time.After(time.Second * 1):
        t.Error("time out")
}

5.channel的關(guān)閉

  • 向關(guān)閉的channel發(fā)送數(shù)據(jù),會(huì)導(dǎo)致panic
  • v,ok <- ch;ok為bool值俩莽,true表示正常接受旺坠,false表示通道關(guān)閉
  • 所有的channel接受者都會(huì)在channel關(guān)閉時(shí),立刻從阻塞等待中返回且上述ok值為false扮超。這個(gè)廣播機(jī)制常被利用取刃,進(jìn)行向多個(gè)訂閱者同時(shí)發(fā)送信號(hào)。如:退出信號(hào)

6.Context與任務(wù)取消

  • 根Context:通過context.Background()創(chuàng)建
  • 子Context:context.WithCancel(parentContext)創(chuàng)建
    • ctx,cancel := context.WithCancel(context.Background())
  • 當(dāng)前Context被取消時(shí)出刷,基于他的子context都會(huì)被取消
  • 接收取消通知 <- ctx.Done()

7.單例模式(懶漢式璧疗,線程安全)

var once sync.Once
var obj *SingletonObj
func GetSingletonObj() *SingletonObj {
    once.Do(func(){
        fmt.Println("Create Singleton obj.")
        obj = &SingletonObj{}
    })
    return obj
}

8、對(duì)象池

9馁龟、sync.Pool總結(jié)

  • 適合于通過復(fù)用崩侠,降低復(fù)雜對(duì)象的創(chuàng)建和GC代價(jià)
  • 協(xié)程安全,會(huì)有鎖的開銷
  • 生命周期受GC影響坷檩,不適合于做連接池等却音,需自己管理生命周期的資源的池化

10、單元測試框架

Benchmark

BDD in Go

項(xiàng)目網(wǎng)站
https://github.com/smartystreets/goconvey

安裝
go get -u github.com/smartystreets/goconvey/convey

啟動(dòng)WEB UI
$GOPATH/bin/goconvey

四矢炼、其他

1系瓢、reflect.TypeOf vs. reflect.ValueOf

  • reflect.TypeOf 返回類型(reflect.Type)
  • reflect.ValueOf 返回值 (reflect.Value)
  • 可以從reflect.Value獲得類型
  • 通過kind的來判斷類型

2、利用反射編寫靈活的代碼

  • 按名字訪問結(jié)構(gòu)的成員
reflect.ValueOf(*e).FieldByName("Name")
  • 按名字訪問結(jié)構(gòu)的方法
reflect.ValueOf(e).MethodByName("UpdateAge").Call([]reflect.Value{reflect.ValueOf(1)})

3句灌、架構(gòu)設(shè)計(jì)模式:Pipe-Filter模式

  • 非常適合與數(shù)據(jù)處理及數(shù)據(jù)分析系統(tǒng)
  • Filter封裝數(shù)據(jù)處理的功能
  • 松耦合:Filter只跟數(shù)據(jù)(格式)耦合
  • Pipe用于連接Filter傳遞數(shù)據(jù)或者在異步處理過程中緩沖數(shù)據(jù)流(進(jìn)程內(nèi)同步調(diào)用夷陋,pipe演變?yōu)閿?shù)據(jù)在方法調(diào)用間傳遞)

4、架構(gòu)設(shè)計(jì)模式:Micro Kernel

特點(diǎn)

  • 易于擴(kuò)展
  • 錯(cuò)誤隔離
  • 保持架構(gòu)一致性

要點(diǎn)

  • 內(nèi)核包含公共流程或通用邏輯
  • 將可變或可擴(kuò)展部分規(guī)劃為擴(kuò)展點(diǎn)
  • 抽象擴(kuò)展點(diǎn)行為胰锌,定義接口
  • 利用插件進(jìn)行擴(kuò)展

5骗绕、更快的JSON解析

EasyJSON采用代碼生成而非反射

  • 安裝
    go get -u github.com/mailru/easyjson/
  • 使用
    easyjson -all <結(jié)構(gòu)定義>.go

6、Http路由規(guī)則

  • URL分為兩種匕荸,末尾是/:表示一個(gè)子樹爹谭,后面可以跟其他子路徑;末尾不是/榛搔,表示一個(gè)葉子诺凡,固定的路徑(以/結(jié)尾的URL可以匹配它的任何子路徑东揣,比如/images會(huì)匹配/images/cute-cat.jpg)
  • 它采用最長匹配原則,如果有多個(gè)匹配腹泌,一定采用匹配路徑最長的那個(gè)進(jìn)行處理
  • 如果沒有找到任何匹配項(xiàng)嘶卧,會(huì)返回404錯(cuò)誤

7、更好的Router

htttps://github.com/julienschmidt/httprouter

8凉袱、性能分析工具

準(zhǔn)備工作

通過文件方式輸出Profile

9、性能調(diào)優(yōu)

常見分析指標(biāo)

  • Wall Time
  • CPU Time
  • Block Time
  • Memory Time
  • GC times/time spent
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末专甩,一起剝皮案震驚了整個(gè)濱河市钟鸵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涤躲,老刑警劉巖棺耍,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異种樱,居然都是意外死亡蒙袍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門嫩挤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來害幅,“玉大人,你說我怎么就攤上這事岂昭∫韵郑” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵约啊,是天一觀的道長叼风。 經(jīng)常有香客問我,道長棍苹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任茵汰,我火速辦了婚禮枢里,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蹂午。我一直安慰自己栏豺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布豆胸。 她就那樣靜靜地躺著奥洼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晚胡。 梳的紋絲不亂的頭發(fā)上灵奖,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天嚼沿,我揣著相機(jī)與錄音,去河邊找鬼瓷患。 笑死骡尽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的擅编。 我是一名探鬼主播攀细,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼爱态!你這毒婦竟也來了谭贪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤锦担,失蹤者是張志新(化名)和其女友劉穎俭识,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吆豹,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鱼的,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痘煤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凑阶。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖衷快,靈堂內(nèi)的尸體忽然破棺而出宙橱,到底是詐尸還是另有隱情,我是刑警寧澤蘸拔,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布师郑,位于F島的核電站,受9級(jí)特大地震影響调窍,放射性物質(zhì)發(fā)生泄漏宝冕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一邓萨、第九天 我趴在偏房一處隱蔽的房頂上張望地梨。 院中可真熱鬧,春花似錦缔恳、人聲如沸宝剖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽万细。三九已至,卻和暖如春纸泄,著一層夾襖步出監(jiān)牢的瞬間赖钞,已是汗流浹背腰素。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仁烹,地道東北人耸弄。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像卓缰,于是被迫代替她去往敵國和親计呈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 數(shù)據(jù)類型 基本數(shù)據(jù)類型 零值 當(dāng)一個(gè)變量或者新值被創(chuàng)建時(shí)征唬, 如果沒有為其明確指定初始值捌显,go語言會(huì)自動(dòng)初始化其值為...
    codefine閱讀 421評(píng)論 0 1
  • 官方網(wǎng)站:https://golang.org/標(biāo)準(zhǔn)庫文檔:https://golang.org/pkg/在線編碼...
    技術(shù)學(xué)習(xí)閱讀 2,326評(píng)論 2 39
  • context.Context類型 context.Context類型(以下簡稱Context類型)是在Go 1....
    尼桑麻閱讀 6,136評(píng)論 0 4
  • 環(huán)境搭建 Golang在Mac OS上的環(huán)境配置 使用Visual Studio Code輔助Go源碼編寫 VS ...
    隕石墜滅閱讀 5,775評(píng)論 0 5
  • 回望青春 伸手挽留 他卻堅(jiān)定又緩慢的走 望眼中年 前方有我的父親 他站在終點(diǎn)對(duì)我揮著手 “不急,慢慢走“ 我抓緊母...
    抓狂的喵星人閱讀 188評(píng)論 0 1