首頁  >  文章  >  你好,我是你的小可愛“GO語言”

你好,我是你的小可愛“GO語言”

-
-原創
2018-03-13 10:10:542901瀏覽

你好,我是你的小可愛“GO語言”

本專欄全面向解讀軟體領域相關知識,偏向技術深度內容,主要涵蓋程式語言、系統架構、開源框架、技術管理等,又分為多個主題,每個主題包含多篇文章。

本文是專欄的第一篇文章,也是GO語言系列的第一篇文章,今天我想從方方面面講下我對於GO語言的大致印象,後續文章會深入介紹各個特性、程式設計技巧。

介紹

從歷史說起,Go語言的作者是Robert Griesemer、Rob Pike和Ken Thompson,其中Ken Thompson以在UNIX和C語言開發中的巨大貢獻為程式設計師所熟知。目前有哪些軟體是用Go語言寫的呢?容器軟體Docker、基礎軟體ETCD和Kubernetes,資料庫軟體TiDB和InfluxDB、訊息系統NSQ、快取元件GroupCache。

可以看到,幾乎在基礎架構軟體的每個領域,都湧現了由Go語言編寫的新軟體,這些軟體的市場佔有率持續攀高。除了作為基礎架構軟體的語言之外,Go語言作為伺服器端通用語言的機會也越來越多,從Beego、Gorilla等Go語言Web框架的熱門程度也可以看出一些發展趨勢。

範例程式

我們透過一個簡單的範例程式來看看GO的編碼風格:

  1. Package main

  2.  import "fmt" 

  3. func main(){     

  4.       fmt.Println("hello,world");

    ##      fmt.Println("hello,world");
  5. ##名詞


  1. #1
  2. # } 
  3. 如何執行上述程式碼呢?GO語言是編譯型語言,GO的工具鏈將程式的原始檔轉變成機器相關的原生指令(二進制),最基礎的工具是run命令,它可以將一個或多個GO源文件(以.go為後綴)進行編譯、鏈接,鏈接後就開始運行生成的可執行文件,看一下實際的操作:
 1.$go run helloworld.go 

列印:hello,world

上面的編譯、連結、運行,都是一次性工作,也就是說下次執行go run指令時,內部流程會全部重做。我們可以透過go build指令產生二進位程序,接著就可以任意呼叫了,如下所示:

$go build helloworld.go

################################## # $./helloworld ############hello,world ############這裡我們提到了編譯型語言,什麼是編譯型語言?如果編譯型語言寫的程式需要被機器認識,它需要經過編譯和連結兩個步驟,編譯是把原始碼編譯成機器碼,連結是把各個模組的機器碼和依賴函式庫串聯起來產生可執行檔。 ######我們來看看編譯型語言的優缺點,由於預編譯過程的存在,對程式碼可以進行最佳化,也只需要一次編譯,運行時效率也會較高,並且可以脫離語言環境獨立運行,缺點是修改後的整個模組需要編譯。 ######相對編譯型語言,解釋型語言只會在執行程式的時候才逐行翻譯。那麼什麼是連結?準確地說是連結和裝入,即在編譯後執行這兩個步驟,程式才能在記憶體中運行。連結是透過連接器完成的,它將多個目標文件連結成一個完整的、可載入的、可執行的目標文件,整個過程包括了符號解析(將目標文件內的應用符號和該符合的定義聯繫起來)和將符號定義與記憶體的位置連結起來兩個步驟。 ######命名規範######GO語言中的函數、常數、變數、型別、語句、標籤、套件的名稱有較統一的命名規則,名稱的開頭是一個字母或底線,後面可以是任意數量的字元、數字或底線,注意,GO語言是區分大小寫的,關鍵字不可以作為名稱。當遇到由單字組成的名稱時,GO程式設計師一般使用「駝峰式」的風格。 ######說到這一點,我們來看看Java的命名規格。以$為例,Oracle官網建議不要使用$或_開始作為變數命名,並且建議在命名中完全不要使用「$」字符,原文是「The convention,however,is to always begin your variable names with a letter, not '$' or '_'”。對於這一條,騰訊的看法是一樣的,百度認為雖然類別名稱可以支援使用「$」符號,但只在系統生成中使用(如匿名類別、代理類別),編碼不能使用。 ######這類問題在StackOverFlow上有很多人提出,主流意見為大家不需要過多關注,只需要關注原先的程式碼是否存在”_”,如果存在就繼續保留,如果不存在則盡量避免使用。也有一位提出盡量不適用”_”的原因是低解析度的顯示器,肉眼很難區分”_”(一個底線)和”__”(兩個下劃線)。 ###

我個人覺得可能是因為受C語言的編碼規範所影響。因為在C語言裡面,系統頭檔裡將巨集名、變數名、內部函數名稱用_開頭,因此當你#include系統頭檔時,這些檔案裡的名字都有了定義,如果與你用的名字衝突,就可能引起各種奇怪的現象。綜合各種訊息,建議不要使用”_”、”$”、空格作為命名開始,以免不利於閱讀或產生奇怪的問題。

對於類別名稱,俄羅斯Java專家Yegor Bugayenko給出的建議是盡量採用現實生活中實體的抽象,如果類別的名字以「-er」結尾,這是不建議的命名方式。他指出針對這條有一個例外,那就是工具類,例如StringUtils、FileUtils、IOUtils。對於介面名稱,不要使用IRecord、IfaceEmployee、RedcordInterface,而是使用現實世界的實體命名。

當然,上述都是針對Java的,與GO無關,GO語言受C語言的影響較多。

變數概述

GO語言包含四種主要的宣告方式:變數(var)、常數(const)、型別(type)和函數(func)。我們來聊聊變量相關的幾點感受:

1. var聲明創建一個具體類型的變量,然後給它附加一個名稱,並且設置它的初始值,每一個聲明有一個通用的形式:var name type = expression。多說一句,GO語言允許空字串,不會報空指標錯誤。

2. 可以採用name:=expression方式宣告變數,注意:=表示聲明,=表示賦值。

如果一個變數生命為var x int,表達式&x(x的位址)取得一個指向整形變數的指針,它的型別是整形指標(*int)。如果值叫做p,我們可以說p指向x,或p包含x的位址。 p指向的變數寫成*p。表達式*p取得變數的值(此例為整形),因為*p代表一個標量,所以它也可以出現在賦值運算子左邊,用於更新變數的值。

  1. x:=1

  2. p:=&x//p是整形指針,指向x 

  3. fmt.Println(*p)//輸出「1」 

  4. #*p=2//等同於x=2 

  5. #fmt.Println(x)//輸出「2」 

注意,相較於Java的NULL,GO表示指標類型的零值是nil。

3. 使用內建的new函數建立變量,表達式new(T)建立一個未命名的T類型變量,初始化為T類型的零值,並傳回其位址(地址類型為*T) 。使用new創建的變數和取其地址的普通局部變數沒有什麼區別,只是不需要引入(或聲明)一個虛擬的名字,透過new(T)就可以直接在表達式中使用。

  1. func newInt() *int{  

  2.     return new(int) 

  3. }  return new(int) 

  1. #等同於:

  2. func newInt() *int{  

  3.     var dummy int     

  4. return &dummy 

##} 

gofmt工具

##GO語言語言提供了許多工具,例如gofmt,它可以將程式碼格式化,讓我們來看看具體是怎麼實現的。

Gofmt會讀取程式並且進行格式化,例如gofmt filename命令,它會列印格式化後的程式碼。我們來看一個範例程式(程式名稱demo.go):你好,我是你的小可愛“GO語言”

執行gofmt demo.go之後,輸出的程式碼如下:你好,我是你的小可愛“GO語言”

垃圾回收

對於高級語言的垃圾回收器,如何知道一個變量是否應該被回收?基本思路是每一個包級別的變量,以及每一個當前執行函數的局部變量,可以作為追溯變數的路徑的源頭,透過指標和其他方式的引用可以找到變數。如果變數的路徑不存在,那麼標量變得不可訪問,因此它不會影響任何其他的計算過程。

因為變數的生命週期是透過它的是否可達來決定的,所以局部變數可以在包含它的循環的一次迭代之外繼續存在。

GO語言的垃圾回收器設計的目標就是非阻塞式回收器,GO1.5實現了10毫秒內的回收(注意,根據實驗證明,這種說法只有在GC有足夠CPU時間的情況下才能成立)。從設計原理來看,Go的回收器是一種並發的、三基色的、標記並清除回收器,它的設計想法是由Dijkstra在1978年提出的,目標是跟現代硬體的屬性和現代軟體的低延遲需求非常匹配。

總結

###綜上所述,每一門新的語言的出現都是有原因的,一般來說是兩大原因:###

1. 出現了當前主流語言無法解決的複雜場景或具體問題;

2. 需要性價比更高的語言。

我想,除了貝爾實驗室會做一些完全出於個人情懷的東西以外,沒有哪一家會隨便佈局無出路的新技術吧。正如Rob Pike所說,“複雜性是以乘積方式增長的”,為了解決某個問題,一點點地將系統的某個部分變得更加複雜,不可避免地也給其他部分增加了複雜性。

在不斷要求增加系統功能、選項和配置,以及快速發布的壓力之下,簡單性往往被忽略了。要實現簡單性,就要求在專案的一開始就濃縮思想的本質,並在專案的整個生命週期中製定更具體的準則,以分辨出哪些變化是好的,哪些是壞的或致命的。

只要夠努力,好的變更就既可以實現目的,又能夠不損害Fred Brooks所謂軟體設計上的「概念完整性」。壞的變化就做不到這一點,致命的變化則會犧牲簡單性而換取便利性。但是,只有透過設計上的簡單性,系統才能在成長過程中保持穩定、安全和自洽。 Go語言不僅包括語言本身及其工具和標準庫,也保持了極端簡單性的行為文化。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn