Go channel 實現歸併排序中的 merge 函數

最近學習 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
}
複製代碼

使用 Go 的感覺

語法近乎簡陋。不過對我而言並沒有大礙,反而喜歡。不太喜歡語法特性(語法糖)太多的語言,亂糟糟的,分散了太多注意力。要是每一個語法特性都是相互正交的,我天然雙手贊同,可是若是多個特性都在作同一件事情,通常對學習者的負擔比較大的(Ruby),也不利於合做。code

編譯型。很少講,幾乎已是俺學習新語言的必要條件了,前期開發效率可能會慢點,可是換來的是更少的 bug,尤爲是對團隊協做,能夠減小不少痛苦。(要是你團隊裏面都是高手,用 Python 天然是爽歪歪,可是這一條件並不老是知足。因此仍是使用能編譯的語言吧 :))排序

相關文章
相關標籤/搜索