go語言有哪些優點?Go語言的核心特性有哪些

Go語言,做爲編程語言的後生,站在巨人的肩膀上,吸取了其餘一些編程語言的特色。java

Go 編程語言是一個開源項目,它使程序員更具生產力。Go 語言具備很強的表達能力,它簡潔、清晰而高效。得益於其併發機制, 用它編寫的程序可以很是有效地利用多核與聯網的計算機,其新穎的類型系統則使程序結構變得靈活而模塊化。 Go 代碼編譯成機器碼不只很是迅速,還具備方便的垃圾收集機制和強大的運行時反射機制。 它是一個快速的、靜態類型的編譯型語言,感受卻像動態類型的解釋型語言。(摘取自官網)python

1、思想

Less can be morec++

大道至簡,小而蘊真git

讓事情變得複雜很容易,讓事情變得簡單才難程序員

深入的工程文化github

2、核心特性

Go語言之因此厲害,是由於它在服務端的開發中,總能抓住程序員的痛點,以最直接、簡單、高效、穩定的方式來解決問題。這裏咱們並不會深刻討論GO語言的具體語法,只會將語言中關鍵的、對簡化編程具備重要意義的方面介紹給你們,體驗Go的核心特性。golang

2.1 併發編程

Go語言在併發編程方面比絕大多數語言要簡潔很多,這一點是其最大亮點之一,也是其在將來進入高併發高性能場景的重要籌碼。編程

不一樣於傳統的多進程或多線程,golang的併發執行單元是一種稱爲goroutine的協程。數組

因爲在共享數據場景中會用到鎖,再加上GC,其併發性能有時不如異步複用IO模型,所以相對於大多數語言來講,golang的併發編程簡單比並發性能更具賣點。安全

在當今這個多核時代,併發編程的意義不言而喻。固然,不少語言都支持多線程、多進程編程,但遺憾的是,實現和控制起來並非那麼使人感受輕鬆和愉悅。Golang不一樣的是,語言級別支持協程(goroutine)併發(協程又稱微線程,比線程更輕量、開銷更小,性能更高),操做起來很是簡單,語言級別提供關鍵字(go)用於啓動協程,而且在同一臺機器上能夠啓動成千上萬個協程。協程常常被理解爲輕量級線程,一個線程能夠包含多個協程,共享堆不共享棧。協程間通常由應用程序顯式實現調度,上下文切換無需下到內核層,高效很多。協程間通常不作同步通信,而golang中實現協程間通信有兩種:1)共享內存型,即便用全局變量+mutex鎖來實現數據共享;2)消息傳遞型,即便用一種獨有的channel機制進行異步通信。

對比JAVA的多線程和GO的協程實現,明顯更直接、簡單。這就是GO的魅力所在,以簡單、高效的方式解決問題,關鍵字go,或許就是GO語言最重要的標誌。

高併發是Golang語言最大的亮點

2.2 內存回收(GC)

從C到C++,從程序性能的角度來考慮,這兩種語言容許程序員本身管理內存,包括內存的申請和釋放等。由於沒有垃圾回收機制因此C/C++運行起來速度很快,可是隨着而來的是程序員對內存使用上的很謹小慎微的考慮。由於哪怕一點不當心就可能會致使「內存泄露」使得資源浪費或者「野指針」使得程序崩潰等,儘管C++11後來使用了智能指針的概念,可是程序員仍然須要很當心的使用。後來爲了提升程序開發的速度以及程序的健壯性,java和C#等高級語言引入了GC機制,即程序員不須要再考慮內存的回收等,而是由語言特性提供垃圾回收器來回收內存。可是隨之而來的多是程序運行效率的下降。

GC過程是:先stop the world,掃描全部對象判活,把可回收對象在一段bitmap區中標記下來,接着當即start the world,恢復服務,同時起一個專門gorountine回收內存到空閒list中以備複用,不物理釋放。物理釋放由專門線程按期來執行。

GC瓶頸在於每次都要掃描全部對象來判活,待收集的對象數目越多,速度越慢。一個經驗值是掃描10w個對象須要花費1ms,因此儘可能使用對象少的方案,好比咱們同時考慮鏈表、map、slice、數組來進行存儲,鏈表和map每一個元素都是一個對象,而slice或數組是一個對象,所以slice或數組有利於GC。

GC性能可能隨着版本不斷更新會不斷優化,這塊沒仔細調研,團隊中有HotSpot開發者,應該會借鑑jvm gc的設計思想,好比分代回收、safepoint等。

  • 內存自動回收,不再須要開發人員管理內存

  • 開發人員專一業務實現,下降了心智負擔

  • 只須要new分配內存,不須要釋放

2.3 內存分配

初始化階段直接分配一塊大內存區域,大內存被切分紅各個大小等級的塊,放入不一樣的空閒list中,對象分配空間時從空閒list中取出大小合適的內存塊。內存回收時,會把不用的內存重放回空閒list。空閒內存會按照必定策略合併,以減小碎片。

2.4 編譯

編譯涉及到兩個問題:編譯速度和依賴管理

目前Golang具備兩種編譯器,一種是創建在GCC基礎上的Gccgo,另一種是分別針對64位x64和32位x86計算機的一套編譯器(6g和8g)。

依賴管理方面,因爲golang絕大多數第三方開源庫都在github上,在代碼的import中加上對應的github路徑就可使用了,庫會默認下載到工程的pkg目錄下。

另外,編譯時會默認檢查代碼中全部實體的使用狀況,凡是沒使用到的package或變量,都會編譯不經過。這是golang挺嚴謹的一面。

2.5 網絡編程

因爲golang誕生在互聯網時代,所以它天生具有了去中心化、分佈式等特性,具體表現之一就是提供了豐富便捷的網絡編程接口,好比socket用net.Dial(基於tcp/udp,封裝了傳統的connect、listen、accept等接口)、http用http.Get/Post()、rpc用client.Call('class_name.method_name', args, &reply),等等。

高性能HTTP Server

2.6 函數多返回值

在C,C++中,包括其餘的一些高級語言是不支持多個函數返回值的。可是這項功能又確實是須要的,因此在C語言中通常經過將返回值定義成一個結構體,或者經過函數的參數引用的形式進行返回。而在Go語言中,做爲一種新型的語言,目標定位爲強大的語言固然不能放棄對這一需求的知足,因此支持函數多返回值是必須的。

函數定義時能夠在入參後面再加(a,b,c),表示將有3個返回值a、b、c。這個特性在不少語言都有,好比python。

這個語法糖特性是有現實意義的,好比咱們常常會要求接口返回一個三元組(errno,errmsg,data),在大多數只容許一個返回值的語言中,咱們只能將三元組放入一個map或數組中返回,接收方還要寫代碼來檢查返回值中包含了三元組,若是容許多返回值,則直接在函數定義層面上就作了強制,使代碼更簡潔安全。

2.7 語言交互性

語言交互性指的是本語言是否能和其餘語言交互,好比能夠調用其餘語言編譯的庫。

在Go語言中直接重用了大部份的C模塊,這裏稱爲Cgo.Cgo容許開發者混合編寫C語言代碼,而後Cgo工具能夠將這些混合的C代碼提取並生成對於C功能的調用包裝代碼。開發者基本上能夠徹底忽略這個Go語言和C語言的邊界是如何跨越的。

golang能夠和C程序交互,但不能和C++交互。能夠有兩種替代方案:1)先將c++編譯成動態庫,再由go調用一段c代碼,c代碼經過dlfcn庫動態調用動態庫(記得export LD_LIBRARY_PATH);2)使用swig(沒玩過)

2.8 異常處理

golang不支持try...catch這樣的結構化的異常解決方式,由於以爲會增長代碼量,且會被濫用,無論多小的異常都拋出。golang提倡的異常處理方式是:

  • 普通異常:被調用方返回error對象,調用方判斷error對象。

  • 嚴重異常:指的是中斷性panic(好比除0),使用defer...recover...panic機制來捕獲處理。嚴重異常通常由golang內部自動拋出,不須要用戶主動拋出,避免傳統try...catch寫獲得處都是的狀況。固然,用戶也可使用panic('xxxx')主動拋出,只是這樣就使這一套機制退化成結構化異常機制了。

2.9 其餘一些有趣的特性

  • 類型推導:類型定義:支持var abc = 10這樣的語法,讓golang看上去有點像動態類型語言,但golang實際上時強類型的,前面的定義會被自動推導出是int類型。

    做爲強類型語言,隱式的類型轉換是不被容許的,記住一條原則:讓全部的東西都是顯式的。

    簡單來講,Go是一門寫起來像動態語言,有着動態語言開發效率的靜態語言。

  • 一個類型只要實現了某個interface的全部方法,便可實現該interface,無需顯式去繼承。

    Go編程規範推薦每一個Interface只提供一到兩個的方法。這樣使得每一個接口的目的很是清晰。另外Go的隱式推導也使得咱們組織程序架構的時候更加靈活。在寫JAVA/C++程序的時候,咱們一開始就須要把父類/子類/接口設計好,由於一旦後面有變動,修改起來會很是痛苦。而Go不同,當你在實現的過程當中發現某些方法能夠抽象成接口的時候,你直接定義好這個接口就OK了,其餘代碼不須要作任何修改,編譯器的自動推導會幫你作好一切。

  • 不能循環引用:即若是a.go中import了b,則b.go要是import a會報import cycle not allowed。好處是能夠避免一些潛在的編程危險,好比a中的func1()調用了b中的func2(),若是func2()也能調用func1(),將會致使無限循環調用下去。

  • defer機制:在Go語言中,提供關鍵字defer,能夠經過該關鍵字指定須要延遲執行的邏輯體,即在函數體return前或出現panic時執行。這種機制很是適合善後邏輯處理,好比能夠儘早避免可能出現的資源泄漏問題。

    能夠說,defer是繼goroutine和channel以後的另外一個很是重要、實用的語言特性,對defer的引入,在很大程度上能夠簡化編程,而且在語言描述上顯得更爲天然,極大的加強了代碼的可讀性。

  • 「包」的概念:和python同樣,把相同功能的代碼放到一個目錄,稱之爲包。包能夠被其餘包引用。main包是用來生成可執行文件,每一個程序只有一個main包。包的主要用途是提升代碼的可複用性。經過package能夠引入其餘包。

  • 編程規範:GO語言的編程規範強制集成在語言中,好比明確規定花括號擺放位置,強制要求一行一句,不容許導入沒有使用的包,不容許定義沒有使用的變量,提供gofmt工具強制格式化代碼等等。奇怪的是,這些也引發了不少程序員的不滿,有人發表GO語言的XX條罪狀,裏面就不乏對編程規範的指責。要知道,從工程管理的角度,任何一個開發團隊都會對特定語言制定特定的編程規範,特別像Google這樣的公司,更是如此。GO的設計者們認爲,與其將規範寫在文檔裏,還不如強制集成在語言裏,這樣更直接,更有利用團隊協做和工程管理。

  • 交叉編譯:好比說你能夠在運行 Linux 系統的計算機上開發運行 Windows 下運行的應用程序。這是第一門徹底支持 UTF-8 的編程語言,這不只體如今它能夠處理使用 UTF-8 編碼的字符串,就連它的源碼文件格式都是使用的 UTF-8 編碼。Go 語言作到了真正的國際化!

3、功能

此處咱們說個小段子:

好久之前,有一個IT公司,這公司有個傳統,容許員工擁有20%自由時間來開發實驗性項目。在2007的某一天,公司的幾個大牛,正在用c++開發一些比較繁瑣可是核心的工做,主要包括龐大的分佈式集羣,大牛以爲很鬧心,後來c++委員會來他們公司演講,說c++將要添加大概35種新特性。這幾個大牛的其中一我的,名爲:Rob Pike,聽後心中一萬個xxx飄過,「c++特性還不夠多嗎?簡化c++應該更有成就感吧」。因而乎,Rob Pike和其餘幾個大牛討論了一下,怎麼解決這個問題,過了一會,Rob Pike說要不咱們本身搞個語言吧,名字叫「go」,很是簡短,容易拼寫。其餘幾位大牛就說好啊,而後他們找了塊白板,在上面寫下但願能有哪些功能。接下來的時間裏,大牛們開心的討論設計這門語言的特性,通過漫長的歲月,他們決定,以c語言爲原型,以及借鑑其餘語言的一些特性,來解放程序員,解放本身,而後在2009年,go語言誕生。

如下就是這些大牛所羅列出的Go要有的功能:

  • 規範的語法(不須要符號表來解析)

  • 垃圾回收(獨有)

  • 無頭文件

  • 明確的依賴

  • 無循環依賴

  • 常量只能是數字

  • int和int32是兩種類型

  • 字母大小寫設置可見性(letter case sets visibility)

  • 任何類型(type)都有方法(不是類型)

  • 沒有子類型繼承(不是子類)

  • 包級別初始化以及明確的初始化順序

  • 文件被編譯到一個包裏

  • 包package-level globals presented in any order

  • 沒有數值類型轉換(常量起輔助做用)

  • 接口隱式實現(沒有「implement」聲明)

  • 嵌入(不會提高到超類)

  • 方法按照函數聲明(沒有特別的位置要求)

  • 方法即函數

  • 接口只有方法(沒有數據)

  • 方法經過名字匹配(而非類型)

  • 沒有構造函數和析構函數

  • postincrement(如++i)是狀態,不是表達式

  • 沒有preincrement(i++)和predecrement

  • 賦值不是表達式

  • 明確賦值和函數調用中的計算順序(沒有「sequence point」)

  • 沒有指針運算

  • 內存一直以零值初始化

  • 局部變量取值合法

  • 方法中沒有「this」

  • 分段的堆棧

  • 沒有靜態和其它類型的註釋

  • 沒有模板

  • 內建string、slice和map

  • 數組邊界檢查

大牛真身

最大牌的當屬B和C語言設計者、Unix和Plan 9創始人、1983年圖靈獎得到者Ken Thompson,這份名單中還包括了Unix核心成員Rob Pike(go語言之父)、java HotSpot虛擬機和js v8引擎的開發者Robert Griesemer、Memcached做者Brad Fitzpatrick,等等。

相關文章
相關標籤/搜索