Golang自2009年發佈第一個版本,2012年發佈1.0版本。在這10年的時間裏,不斷有開發者加入Golang的陣營中,不斷共建Golang生態。其中比較有表明性的Golang編寫軟件做品是Docker和Kubernetes。從目前Golang的發展時間和社區活躍度來看,Golang無疑是一門成功的編程語言。程序員
有次微信公開課中,微信之父張小龍提到微信成功的祕訣就是簡單,把全部功能作到最簡單,UI最簡單,用戶使用最簡單。這樣使得競品沒法抄襲,由於微信是最簡單的,對手加了一點東西都是冗餘。那麼什麼使得Golang這麼成功呢?編程
你可能會提到下面的緣由:微信
可是這些不是語言特性,全都很是重要可是不是真正的答案。比較少談起的是:接口或者併發這樣真正的語言特性。真正的緣由是簡單。Golang是簡單的,至少相比於當前的編程語言來講是簡單的。簡單有不少面,簡單同時也是複雜的。語言使用上的簡單對應的確定是底層實現原理的複雜,和設計人員的精美設計的結果。網絡
Java,JavaScript,C#,C++,PHP,Python 這些編程語言積極的互相借鑑語言特性,例如這些語言都會有class(類)。它們正在彙總爲一個簡單的大型語言併發
編程語言須要不一樣的維度考慮:編程語言
邏輯編程(logic programming)函數
過程編程(procedural programming)工具
函數編程(functional programming)測試
面向對象編程(object-oriened programming)優化
併發編程(concurrent programming)
若是全部的編程語言都彙總在一塊兒,那麼咱們思考的編程模式就會是同樣的。可是有不一樣的思考方式是好的,須要不一樣的編程語言解決不一樣的問題。咱們要的不是僅僅只有一個工具,而是一堆工具,不一樣的工具聚焦解決不一樣的問題。前面提到的語言,如Java8,C++14正在討論新的特性,這些語言經過加入特性在不斷的競爭。當某個語言出現了某個特性時,另外的語言必定會跟隨,例如C++11/14加入的類型推導,不禁得讓人想起了腳本語言Python。這些語言在發展的過程會變得愈來愈複雜,同時也會變得愈來愈類似。它們會膨脹得沒有區分度。
Golang沒有嘗試像其餘編程語言,不在特性上競爭。Golang 1.0版本發佈時,這門語言的特性就已經固定了。不少Golang的新手會要求Golang具備一些他們知道的其餘編程語言的特性。可是這些特性不屬於Golang,這門編程語言的特性已經固定了。加入新特性不會使Golang變得更好,只會使它變得更大,更臃腫。
若是一門編程語言有太多特性,你會浪費時間在挑選用哪一個的問題上。而後實現,精簡,可能會回想和重作。
實際工做中,常常會發生的一幕是,有人會問,「爲何這些代碼要這樣寫,這段代碼是怎麼工做的」,這我的多是其餘人,更有多是你本身。這些代碼是很難簡單的能理解到,由於它用了一個更加複雜的編程語言,因爲複雜編程語言的諸多特性,可能會致使不少分支的結果,因此咱們須要分析這段代碼的各類可能性,一不當心就會掉到坑裏面。因此對於程序員來講,更傾向於只有一種實現方法,或者至少應該是儘可能少的實現方法,更簡單的實現方法。更多的特性會增長編程語言的複雜度,咱們想要簡單的編程語言。更多的特性會讓可讀性受損,咱們想要可讀性。可讀性是最重要的。由於可讀性意味着可靠性,若是你可以讀懂代碼和它意味着什麼,就會很容易明白它的工做原理。若是它出現問題也會更容易修復。
簡單的交互方式是簡單的特性。簡單是Golang的目標。
Golang實際上實現原理很是複雜,可是它看起來很簡單,使用很簡單。語法很是簡單和準確,沒有歧義,沒有驚喜。這須要Golang的創始人/團隊通過大量的設計、實現和優化。因此簡單是掩蓋複雜的一門藝術。
下面會介紹Golang的幾個簡單特性:Gc機制(垃圾回收),goroutine,interface(接口),package(包)。每一個簡單的特性後面都是複雜的實現。
垃圾回收多是最好的用簡單掩蓋複雜的特性。實現起來很是難,可是很值得。由於有gc機制咱們Golang代碼編寫得更簡單。寫代碼的時候不須要關心「擁有者」。
Golang原生就支持了併發,而不是依賴第三方庫。Golang併發包括下面三個元素:goroutines(執行體),channels(通訊),select(協調)。
這裏咱們只須要暫時先關注goroutine,經過go function(args)啓動一個獨立運行的goroutine。三個字符’g’ ‘o’ ‘ ’就能啓動一個goroutine。很難作到比這更簡單的了。和gc機制同樣,將編程人員須要關心的東西最小化。棧的大小,返回值和完成狀態,線程 ID等都不用關心。雖然goroutine的實現很複雜,依賴於gc機制和棧管理,可是編程人員不用關心這些,只須要go就能啓動一個goroutine。
接口僅僅是方法的集合,沒有數據。很簡單的想法。
type Reader interface { Read([]byte)(int, error) } var r Reader = os.Stdin //靜態檢查 var x interface{} = os.Stdin //靜態檢查 r = x.(Reader) //動態檢查,必定要是精準斷言,不然會panic
在靜態類型語言中加入動態類型轉換,這些須要當心精準的設計。接口的賦值在運行時完成。最好是用「comma, ok」的語法,不然失敗會panic。接口是Golang最有區分度和最強大的特性。深度影響了包的設計。另外包容許組合,例如能夠將io.Reader和io.Writer組合爲io.ReadWriter。感受很簡單,實則底層原理很複雜。
一個結構化程序和庫的設計。
package big
…
import 「math/big」
包的設計花費了Golang團隊大量時間去設計。容許組合,可擴展,共享,數據隱藏(大小寫),還有隔離 …。包的設計涉及到程序的設計,語法,命令,編譯,連接,測試等等。可是對於Golang編程人員來講只須要使用package定義包,用import引用包便可。這也是用簡單掩蓋複雜的一個例子。
上述的示例都是爲了說明Golang使用是很是簡單,實現很是複雜。做爲Golang的使用者,咱們只須要清楚它的使用便可,而無需關心Golang的複雜實現,這也是Golang團隊的目標。
下面是一個簡單的Golang程序:
package main import ( "fmt" "log" "net/http" ) func 你好_Gophers(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "你好 Gophers!\n") } func main() { http.HandleFunc("/", 你好_Gophers) err := http.ListenAndServe("localhost:12345", nil) if err != nil { log.Fatal("ListenAndServer:", err) } }
掩蓋了下面的複雜過程:
Unicode和UTF8處理
包的引用和使用
Fprintf直接對接網絡鏈接
函數做爲參數傳遞(HandleFunc)
真正的併發 —server並無阻塞
Golang是使用簡單,底層實現原理複雜的一門編程語言。