這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
寫在前面:
近來關於對Golang的討論有很多,七牛的幾個大牛們也斷定Go語言在未來將會快速發展,並且很可能會取代Java成為互連網時代最受歡迎的程式設計語言。Go語言是google推出的程式設計語言,在已經成功的給世人創造了改變人們生活的作業系統之後,google似乎感覺有必要再為世人帶來一款強大的程式設計語言,而Go語言依靠自己眾多友好的特性也不負眾望正在被開發人員接觸,我有幸在學習高效能並發編程的時候認識了Go語言,在瞭解了Go的一些特性之後決定系統的學習一番。我發現關於Go的學習資料並不多,以至於我需要自己寫一些東西。這裡的內容大多來自七牛團隊的《Go語言編程》一書。這裡也會按照書中組織的章節進行學習。當然如果一些知識點事互連網上已經有的,這裡直接進行轉載了。
-Written by Lingtao in Nanjing.
http://blog.csdn.net/michael_kong_nju/article/details/45423197
按照書中說的,Go語言具有以下的特徵,下面我們分別來進行介紹。
自動記憶體回收
更豐富的內建類型
函數多傳回值
錯誤處理
匿名函數和閉包
類型和介面
並發編程
反射
語言互動性
1. 自動記憶體回收
從C到C++,從程式效能的角度來考慮,這兩種語言允許程式員自己管理記憶體,包括記憶體的申請和釋放等。因為沒有記憶體回收機制所以C/C++運行起來速度很快,但是隨著而來的是程式員對記憶體使用量上的很謹小慎微的考慮。因為哪怕一點不小心就可能會導致“記憶體泄露”使得資源浪費或者“野指標”使得程式崩潰等,儘管C++11後來使用了智能指標的概念,但是程式員仍然需要很小心的使用。後來為了提高程式開發的速度以及程式的健壯性,java和C#等進階語言引入了GC機制,即程式員不需要再考慮記憶體的回收等,而是由語言特性提供記憶體回收行程來回收記憶體。但是隨之而來的可能是程式運行效率的降低。
“Go語言作為一門新生的開發語言,當然不能忽略記憶體管理這個問題。又因為Go語言沒有C++
這麼“強大”的指標計算功能,因此可以很自然地包含記憶體回收功能。因為記憶體回收功能的支援,開發人員無需擔心所指向的對象失效的問題,因此Go語言中不需要delete關鍵字,也不需要free()方法來明確釋放記憶體”.
2. 更豐富的內建類型
其實作為一種新興的語言,如果僅僅是為了某種特定的用途那麼可能其內建類型不是很多,僅需要能夠完成我的功能即可,但是Go語言“不僅支援幾乎所有語言都支援的簡單內建類型(比如整型和浮點型等)外,還支援一些其他的進階類型,比如字典類型,map要知道這些類型在其他語言中都是通過包的形式引入的外部資料類型。數組切片(Slice),類似於C++ STL中的vector,在Go也是一種內建的資料類型作為動態數組來使用。這裡滿有一個頗為簡單的解釋:”既然絕大多數開發人員都需要用到這個類型,為什麼還非要每個人都寫一行import語句來包含一個庫?”
3. 支援函數多傳回值
在C,C++中,包括其他的一些進階語言是不支援多個函數傳回值的。但是這項功能又確實是需要的,所以在C語言中一般通過將傳回值定義成一個結構體,或者通過函數的參數引用的形式進行返回。而在Go語言中,作為一種新型的語言,目標定位為強大的語言當然不能放棄對這一需求的滿足,所以支援函數多傳回值是必須的,例如:
> func getName()(firstName, middleName, lastName, nickName string){> return "May", "M", "Chen", "Babe" } //定義了一個多傳回值的函數getName> > fn, mn, ln, nn := getName() //調用賦值> _, _, lastName, _ := getName() //預設調用
4. 錯誤處理
在傳統的OOP編程中,為了捕獲程式的健壯性需要捕獲異常,使用的方法大都是try() catch{}模組,例如, 在下面的java代碼中,可能需要的操作是:
Connection conn = ...;try { Statement stmt = ...; ...//別的一些異常捕獲finally { stmt.close(); }finally { conn.close(); }
而在Go中引入了三個關鍵字,分別是 defer、panic和recover,其中使用defer關鍵字語句的含義是不管程式是否出現異常,均在函數退出時自動執行相關代碼。
所以上面你的java代碼用Go進程重寫只有兩行:
conn := ...defer conn.Close()
另外兩個關鍵詞後面再討論。所以“Go語言的錯誤處理機制可以大量減少代碼量,讓開發人員也無需僅僅為了程式安全性而添加大量一層套一層的try-catch語句。這對於代碼的閱讀者和維護者來說也是一件很好的事情,因為可以避免在層層的代碼嵌套中定位業務代碼。”
5. 匿名函數和閉包
關於這個功能介紹的不多,大概就是說Go中的函數也可以作為參數進行傳遞:
“在Go語言中,所有的函數也是實值型別,可以作為參數傳遞。Go語言支援常規的匿名函數和閉包,比如下列代碼就定義了一個名為f的匿名函數,開發人員可以隨意對該匿名函數變數進行傳遞和調用:
f := func(x, y int) int {
return x + y
}
”
6. 類型和介面
這個特性是Go在實現OPP時候的一些特性,主要有這麼幾點:
第一: Go語言沒有很複雜的物件導向的概念,即沒有繼承和重載,其類型更像是C中的struct,並且直接使用了struct關鍵字,僅僅是最基本的類型組合功能。但是,儘管不支援這些文法特性,但是Go的OOP卻同樣可以實現這些功能,只是實現的形式上會有不同而已。
即這裡需要介紹的“非侵入型”介面的概念。
舉個例子:
在C++中,一般會這樣定義一個介面和類型的
// 抽象介面
interface IFly
{
virtual void Fly()=0;
};
// 實作類別
class Bird : public IFly
{
public:
Bird() {}
virtual ~Bird() {}
void Fly()
{
// 以鳥的方式飛行
}
};
//使用的時候
void main()
{
IFly* pFly = new Bird();
pFly->Fly();
delete pFly;
}需要你自己以虛函數的形式定義一個介面,並且讓類型繼承這個介面並重寫虛方法。在使用的時候需要進行動態綁定。
而在Go中實現相同的功能,你只需要
type Bird struct {
…
}
func (b *Bird) Fly() {
// 以鳥的方式飛行
}
type IFly interface {
Fly()
}
func main() {
var fly IFly = new(Bird)
fly.Fly()
}
可以看出,“雖然Bird類型實現的時候,沒有聲明與介面IFly的關係,但介面和類型可以直
接轉換,甚至介面的定義都不用在類型定義之前,這種比較鬆散的對應關係可以大幅降低因為接
口調整而導致的大量代碼調整工作”。
7. 並發編程
其實到目前為止,最吸引我的就是這個特性,而且我之前說了如果不是因為要做伺服器的高並發我可能根本就不知道Go這種語言,在上一篇文章http://blog.csdn.net/michael_kong_nju/article/details/45420047 中討論了為什麼Go可以實現大規模的並發的原理,這裡不做詳細的介紹,只給出實現方法,即
“Go語言引入了goroutine概念,它使得並發編程變得非常簡單。通過使用goroutine而不是裸用作業系統的並發機制,以及使用訊息傳遞來共用記憶體而不是使用共用記憶體來通訊,Go語言讓並發編程變得更加輕盈和安全。通過在函數調用前使用關鍵字go,我們即可讓該函數以goroutine方式執行,goroutine是一種比線程更加輕盈、更省資源的協程。”
“同時,Go語言實現了CSP(通訊順序進程,Communicating Sequential Process)模型來作為goroutine間的推薦通訊方式,在CSP模型中,一個並發系統由若干並行啟動並執行順序進程組成,每個進程不能對其他進程的變數賦值。進程之間只能通過一對通訊原語實現協作。Go語言用channel(通道)這個概念來輕巧地實現了CSP模型。channel的使用方式比較接近Unix系統中的管道(pipe)概念,可以方便地進行跨goroutine的通訊。”
“另外,另外,由於一個進程內建立的所有goroutine運行在同一個記憶體位址空間中,因此如果不同的goroutine不得不去訪問共用的記憶體變數,訪問前應該先擷取相應的讀寫鎖。Go語言標準庫中的sync包提供了完備的讀寫鎖功能。”
8. 支援反射
這裡的反射(reflecttion)和JAVA中的反射類似,可以用來擷取物件類型的相信資訊,並動態操作對象。因為反射可能會對程式的可讀性有很大的幹擾,所以,在Go中只是在特別需要反射支援的地方才實現反射的一些功能。“反射最常見的使用情境是做對象的序列化(serialization,有時候也叫Marshal & Unmarshal)。例如,Go語言標準庫的encoding/json、encoding/xml、encoding/gob、encoding/binary等包就大量依賴於反射功能來實現。”
9. 語言的互動性
這裡的互動性主要是和C的互動性,之所以這樣是因為Go語言的開發人員是最初貝爾實驗室建立Unix系統以及C語言的一般人,包括:
肯·湯普遜(Ken Thompson,http://en.wikipedia.org/wiki/Ken_Thompson):設計了B語言和C語言,建立了Unix和Plan 9作業系統,1983年圖靈獎得主,Go語言的共同作者。
在Go語言中直接重用了大部份的C模組,這裡稱為Cgo.Cgo允許開發人員混合編寫C語言代碼,然後Cgo工具可以將這些混合的C代碼提取並產生對於C功能的調用封裝代碼。開發人員基本上可以完全忽略這個Go語言和C語言的邊界是如何跨越的。
例如書中一個例子,在Go語言中直接調用了C標準庫的puts函數。
package main/*#include <stdio.h>*/import "C"import "unsafe"func main() {cstr := C.CString("Hello, world")C.puts(cstr)C.free(unsafe.Pointer(cstr))}
以上就是書中總結的Go語言的9大特性,這裡面我看完之後根據自己的體會以及書中的一些總結進行了匯總。對於想瞭解Go這麼語言,以及準備進入這個領域的人可以對Go有一個大概的認識。如果想深入的學習可以去看七牛雲端儲存團隊出的《Go語言編程》。我後面也會繼續學習。