最近學習 Go,可是苦於沒有項目練手,因而便逼迫本身:若是想到什麼有趣的東西,看能不能用 Go 實現一遍,因而便有了這篇流水文。bash
歸併排序中的 merge 函數,相信每一個人都很熟悉,網上隨便搜搜都有一大堆文章,這裏再也不贅述細節。一開始,我用的是常規套路,不過以爲沒啥意思,無非是「換湯不換藥,感受仍是在拿本身熟悉的語言寫東西」。數據結構
聯想到 Go 的 channel 彷佛能在某種程度上知足個人要求,再加上 Goroutine 這種東西,便想:是否是也能利用利用這兩個語言特性。函數
channel 這個數據結構,在 Go 中有比較豐富的含義,但我基本上把它當隊列使用。Goroutine 也同樣,我基本把它等同於「用戶態線程」(二者都很牛逼,不過做爲應用層的開發者,有時候並不想深究太多,一切都往簡單方向理解)。學習
因爲我只是練手,因此我想到的 API 長這樣:ui
Merge(ch1, ch2): outChan
複製代碼
給定兩個有序的 channel,而後將其合併爲一個有序的 channel。spa
因而個人實現以下:線程
func Merge(ch1 <-chan int, ch2 <-chan int) <-chan int {
out := make(chan int)
go func() {
// 等上游的數據 (這裏有阻塞,和常規的阻塞隊列並沒有不一樣)
v1, ok1 := <-ch1
v2, ok2 := <-ch2
// 取數據
for ok1 || ok2 {
if !ok2 || (ok1 && v1 <= v2) {
// 取到最小值, 就推到 out 中
out <- v1
v1, ok1 = <-ch1
} else {
out <- v2
v2, ok2 = <-ch2
}
}
// 顯式關閉
close(out)
}()
// 開完goroutine後, 主線程繼續執行, 不會阻塞
return out
}
複製代碼
語法近乎簡陋。不過對我而言並沒有大礙,反而喜歡。不太喜歡語法特性(語法糖)太多的語言,亂糟糟的,分散了太多注意力。要是每一個語法特性都是相互正交的,我天然雙手贊同,可是若是多個特性都在作同一件事情,通常對學習者的負擔比較大的(Ruby),也不利於合做。code
編譯型。很少講,幾乎已是俺學習新語言的必要條件了,前期開發效率可能會慢點,可是換來的是更少的 bug,尤爲是對團隊協做,能夠減小不少痛苦。(要是你團隊裏面都是高手,用 Python 天然是爽歪歪,可是這一條件並不老是知足。因此仍是使用能編譯的語言吧 :))排序