[Go] 閱讀心得 不負責任翻譯 Golang Frequently Asked Questions (FAQ) PART4 END


https://golang.org/doc/faq

官方FAQ 提供一些有趣的資訊,很認真的試圖都理解一下,由於內容太多,拆成幾個部分來看。

PART4這裡有
Functions and Methods  Control flow Packages and Testing Implementation 
Performance Changes from C



--Functions and Methods--

Why do T and *T have different method sets?

接收到型態T的對象,有型態T所有的method,但如果是接收到型態*T,則會擁有型態T和型態*T的所有method。

如果interface裡面包含*T,那麼操作的行為會是pointer,如果是T,那操作的行為只能是value的處理方式。

如果是傳value,copy值之後,就跟原本被copy的部分沒關係了。



What happens with closures running as goroutines?


func main() {
    done := make(chan bool)

    values := []string{"a", "b", "c"}
    for _, v := range values {
        go func() {
            fmt.Println(v)
            done <- true
        }()
    }

    // wait for all goroutines to complete before exiting
    for _ = range values {
        <-done
    }
}

這個範例是在學GO蠻經典的例子,結論是永遠不要在gorutine裡面直接使用外面的變數。

因為goruntine宣告後並不是馬上建立的,可能等一下才建立,以及複數個gorutine建立起來可能沒有順序性,此時外面的變數已經不知道跑到哪裡去了。

有兩個比較直觀的解法,一個是每次都直接將變數傳入goruntine的function。

一個是傳入之前都先copy一份。(這個感覺跟每個與scope處理的範圍有關,比較不直覺。)



--Control flow--

Does Go have the ?: operator?

Go 沒有問號冒號的運算符號,請愛用if else 達成你的目標。




--Packages and Testing--


How do I create a multifile package?

在package的檔案可以分成多個沒關係,對於外面來使用都會視為同一檔案,並且不需要額外宣告或引用。



How do I write a unit test?

在單一檔案建立有 _test.go,參考go test,GO 為unit test有所準備。



Where is my favorite helper function for testing?

GO 有一包testing的package專門處理測試,但go裡面沒有斷言(這裡的斷言是斷value落在哪裡,而不是型態的斷言)。

過去在其他語言有發現斷言的結果有問題,最常被舉例的就是判斷『質數』的問題,2、3、5、7或2、4、8、16,跑到2就報錯了,後續往往沒有測到。

GO 的理念是將測試結合在這裡語言裡面,而不需要額外的測試框架來滿足測試需求。

測試的寫法可以參考https://golang.org/src/fmt/fmt_test.go



Why isn’t X in the standard library?

會出現在GO標準庫的libaray,是在執行期間,或需要配合作業系統,格式或協定轉換,或者go常用的基本函式的內容。

如http、io、json、xml 等等,但這沒有一個絕對的標準,完全是視今日所需。

往後的新原始碼會頃向放在外面,而非內建的標準庫,因為go的開發為了保證向下相容性,所以越多東西放進標準庫,越需要顧忌向下相容的保證。



--Implementation--


What compiler technology is used to build the compilers?

原本的gccgo是用c++ 寫成的,gc是用c寫成的。

不過後來1.5版以後,go的compillier是用go寫出來的(超酷!)。



How is the run-time support implemented?

原本run-time的編譯是用C寫成的,承上已經改為用GO寫出來的。

如果要用c語言的lib,gccgo還是可以幫忙做這件事情。



Why is my trivial program such a large binary?

即使只是用了C語言印出hello world,也要花750KB,這件事情在GO裡面印出也要花1MB以上。

原因是某些小東西看似不起眼,但他的靜態link,在run-time的動態型態,reflect,panic trace都要花費空間和資源做處理。



Can I stop these complaints about my unused variable/import?

未使用的變數可能造成錯誤(被誤用?),以及拖慢編譯和運行的速度,所以GO拒絕未使用的變數出現在裡面。

犧牲短期的便利,造成長期的效率和乾淨性是可以被接受的。

可以把他從error調整成warning層級嗎?GO拒絕,況且對於GO來說,編譯並沒有warning,只有error。(WOW WOW WOW ! 這令人驚訝)

如果值得警告,就值得去修理,若不值得修理,警告就只是對於編譯器的一種干擾,所以只有error!(霸氣…)

(下面那段我不太懂,略)



Why does my virus-scanning software think my Go distribution or compiled binary is infected?

GO的編譯檔被防毒軟體被誤認中毒是常發生的,尤其是在windows,這些編譯軟體常不認識GO。

請向你的防毒軟體公司回報bug吧。



--Performance-- 

Why does Go perform badly on benchmark X?(大部分不是很懂)

大概是說有些benchmark測試的面向,對於golang來講沒有什麼可比性,因為一些作法和注重的部分不一樣。

但大部分情況下,go還是很有競爭力的。



--Changes from C--


Why is the syntax so different from C?

GO認為程式語法應該是簡單,輕量,C語言的語法太多關鍵字、複雜,因此與C語言的語法有大幅不同。



Why are declarations backwards?

將型態宣告放在後面,目的是為了清楚,並一致表示這些宣告的變數都是這個型態。

如C語言,型態的宣告放在前面,變數a、和變數b用逗號隔開放在同一行,兩個變數的型態是不一樣,這樣也不夠清楚。



Why are ++ and – statements and not expressions? And why postfix, not prefix?

(這邊牽扯很多語意邏輯的東西,我不是很清楚)。

大意是說放前面雖然也可以運作得很好,但是放後面是比較傳統的做法,就放後面吧。



Why are there braces but no semicolons? And why can’t I put the opening brace on the next line?

這邊也是compilier的處理,沒有分號在GO裡面不是偷偷插在最後面,而是靠語意分析器斷每一句。

大括號單純存在一行會造成很多問題,因此GO拒絕這麼做。

加上gofmt處理成單一格式,對於語意分析器會好處理很多,就不用另外建立特殊規則去處理一些開放性的格式。



Why do garbage collection? Won’t it be too expensive?

以過去幾年GC技術處理的進步,GO對於GC的記錄有信心,能做到消耗最低的資源消耗以及不會讓系統延遲。

對於並發和多線程,記憶體管理是很重要的課題,尤其在多線程東西的傳遞,要做到安全的釋放是困難的。

(後面不太懂,大意大概是GO認為要做GC這件事)

因為GO幫忙做了GC,所以interface的使用大可不用擔心太多記憶體的問題。

GO語言本身提供的可控制性,遠大於內部GC的有限控制,若有疑問請參考profiling文件。(部分說明不太懂)


Created Date : 2018/08/10

Last Updated Date : 2018/08/10

留言

這個網誌中的熱門文章

[Go] 型態轉換 type convert

[Go] Golang用法 package import 前面的底線

[Go] 指標 pointer with golang