官术网_书友最值得收藏!

2.1 變量

變量在使用時往往分為聲明和賦值兩個步驟。其中聲明除了給定占位符外,更重要的是要指定數據類型。因為在應用程序執行時,變量都要經歷內存分配,而分配的內存大小主要取決于數據類型。

2.1.1 變量聲明

在Go語言中,可以利用var關鍵字來聲明一個變量,例如:

    var length int

var是variable的縮寫形式,表示這是一個變量聲明;length為變量名;int則為變量的數據類型。對于多個相同數據類型的變量,也可以進行一次性聲明。例如,同時聲明兩個int類型的變量,其名稱分別為length和size,對應的代碼如下:

    var length, size int

對于多個變量,如果它們的數據類型不同,則需要分別進行聲明,例如:

    var length, size int
    var success bool

除此之外,還可以共用var關鍵字,以上變量聲明可以寫作如下形式。

    var (
    length, size int
    success bool
    )

而在Java等編程語言中,則直接省略了這一關鍵字。例如,在Java中聲明一個變量,使用如下語法:

    int length;

一向崇尚簡單的Go語言,破天荒地增加了var來表示變量,在變量聲明方面比Java多出一個關鍵字。這是因為Go語言為常量單獨保留了一個關鍵字const,var和const分別對應于變量和常量的聲明。

2.1.2 變量賦值

變量在聲明后,可以利用“=”來對變量進行賦值操作。例如:

    var length int
    length = 10
1.多重賦值

對于多個變量,可以利用如下語句同時進行賦值:

    var length, size int
    length, size = 10, 20

此時,變量length和size分別被賦值為10和20。在一行代碼中為多個變量一起賦值,這就是我們期盼已久的多重賦值。我們自然也會想到,是否可以利用多重復賦值語句來交換兩個變量的值呢?

代碼清單2-1演示了變量a和b的值進行互換的常規做法(不考慮數據溢出的極端情況)。

代碼清單2-1 在不引入第三個變量的情況下,交換兩個變量的值

運行該代碼段,在控制臺上的輸出如下:

    原始值:a= 10 , b= 20
    執行后:a= 20 , b= 10

可見成功實現了a, b值的互換。在實現該功能之余,我們對于完成如此簡單的功能卻需要3條語句,多少會感到有些沮喪。而在Go語言中,可以直接利用多重賦值實現。對應的代碼如代碼清單2-2所示。

代碼清單2-2 利用多重賦值實現兩值互換

在上面的代碼段中,我們直接利用如下代碼完成了a、b值的交換。

    a, b = b, a

不只是數值型的互換,利用多重賦值還可以實現其他數據類型的互換,當然,前提是兩個變量有著相同的數據類型。

2.變量的零值

在Go語言中,如果一個變量只進行了聲明而沒有對它賦值,其實也會依據數據類型賦予變量零值。以下是各種數據類型對應的零值。

(1)整型的零值為0。

(2)浮點型的零值為0.0。

(3)布爾型的零值為false。

(4)字符串類型的零值為空字符串("")。

(5)數組類型的零值是按元素的數據類型將其所有元素置為零值。

(6)接口類型(interface)、切片(slice)、通道(channel)、字典(map)、指針(pointer)、函數(function),它們的零值均為空(nil)。

(7)結構體(struct)的零值是對其字段/元素填充零值。

這與大多數編程語言的規則一致,比較特殊的是結構體和數組。通過二者的填充規則我們可以看出,Go語言總是盡量避免真正意義上的空值。如此一來,也間接地減少了類似Java/C++中的空指針異常帶來的困擾。

2.1.3 同時進行變量聲明和賦值

我們可以在變量聲明的同時對它賦值,例如:

    var a int = 10

在IDE工具GoLand中,該代碼行中的“int”會呈現淺灰色。將光標置于int關鍵字上,GoLand會給出優化提示——類型可以忽略,如圖2-1所示。

圖2-1 GoLand中忽略類型關鍵字的提示

在提示窗口中單擊“More actions...”,會給出修正操作建議。最直接的操作建議是刪掉int關鍵字。我們直接刪掉int關鍵字,在沒有指定數據類型的情況下仍可以正常編譯執行,這是因為Go語言的另外一項功能——類型推斷。

類型推斷是指,如果變量聲明和賦值在同一條語句中完成,那么編譯器可以從具體值中推斷出數據類型,而不需要顯式聲明數據類型。例如:

    var a int = 10

可以簡寫為:

    var a = 10

更進一步,利用操作符“:=”可以對該語句在形式上進行簡化。

    a := 10

需要注意的是,這3種寫法都是正確的寫法,實現的功能也完全相同,只是代碼形式不同而已。當然,采用哪種寫法完全依賴程序員的個人風格和團隊的代碼規范。

類型推斷也與運行平臺息息相關。例如,對于整數,往往會被推斷為int;對于浮點數,往往會被推斷為float64(64位平臺)。如果類型推斷的結果并不是程序員的本意,那么顯式指定變量的數據類型仍然是必要的。

在上面的示例中,var a int = 10中的int是冗余的類型聲明。如果要求變量a的類型為uint,則必須顯式指定數據類型,如下所示。

    var a uint = 10

因為uint與類型推斷獲得的結果(int)不同,所以該語句在GoLand等IDE中不會出現優化提示。

2.1.4 多重賦值與“:=”操作符

操作符“:=”表示同時進行變量聲明和賦值,因此,對一個變量進行多次“:=”操作,將會出現編譯錯誤,例如:

    a := 10
    a := 20

對變量a的第二次賦值需要使用“=”進行賦值,而不是“:=”,因為不能對同一個變量進行兩次聲明。正確的代碼如下:

    a := 10
    a = 20

另外,我們可以利用一條語句來對兩個變量同時進行賦值。如果其中一個已經聲明過,而另外一個未聲明,那么應該使用“:=”還是“=”呢?

這種混合情況,應該使用“:=”。Go語言會兼容處理這種情況。即使變量a已經聲明過,但變量b并未聲明過,因此利用“:=”進行多重聲明和賦值也是合法的,如圖2-2所示的代碼不會出現編譯錯誤。

圖2-2 多重賦值與“:=”的使用

2.1.5 沒有多余的局部變量

Go語言中的局部變量有一個很獨特的特點——沒有一個變量是多余的。這意味著我們不能聲明一個局部變量卻在整個程序中不使用它。

例如,聲明了一個變量a并為它賦值10,但在后續代碼中,變量a未被真正使用到。此時編譯執行該代碼,將會出現“未使用的變量a(Unused variable 'a')”的錯誤提示,如圖2-3所示。

圖2-3 聲明但并未使用局部變量,將會出現編譯錯誤

這一規則保證了代碼的盡量整潔。Java開發利器Intellij IDEA和GoLand屬于同一IDE家族。對于Java程序中出現的聲明但未使用的局部變量,Intellij同樣可以識別,但只會在變量處給出優化提示(如同圖2-1中的淺灰色樣式)。可見,聲明但不使用變量,是與編程整潔性相悖的,Go語言對這一點執行得更加嚴格。

2.1.6 全局變量

對于習慣了面向對象編程的程序員來說,一提到變量,潛意識里總是將它識別為局部變量,這可能是因為面向對象編程中很少提到全局變量的概念。但在Go語言中,全局變量(variable)是和函數處于同一地位的成員。全局變量的作用域為整個.go文件中的任意位置,同時,也可以被其他.go文件導入并引用。代碼清單2-3演示了全局變量的定義和使用。

代碼清單2-3 全局變量的定義和使用

在上面的代碼中,聲明了一個全局變量a,變量a在整個.go文件的所有函數中均可訪問。

2.1.7 全局變量與鏈接

除了作用域外,我們從另外一個角度來看看全局變量與局部變量的區別:僅聲明,不使用。

在圖2-4中,聲明了一個全局變量a,并將它賦值為10,但沒有任何一處代碼使用到該變量。當編譯時,不會出現編譯錯誤。

圖2-4 聲明但并未使用全局變量,不會出現編譯錯誤

同樣是變量,為什么未使用局部變量會出現編譯錯誤,而全局變量不會呢?甚至在類似GoLand這樣的強大的IDE工具中,連優化、警告一類的提示都沒有。

這是因為編譯器(Compiler)不能識別出全局變量是否真的不會被引用。因為全局變量意味著可以被外部引用,而非限于當前.go文件(在第18章會看到在匯編文件中引用.go文件中的全局變量的例子)。那么全局變量到底在哪些地方被引用呢?其實是在鏈接階段,由鏈接器(Linker)完成引用。而鏈接階段處于編譯階段之后,因此,編譯器無法識別全局變量的引用情況,也就不會出現編譯錯誤。

主站蜘蛛池模板: 沙坪坝区| 延吉市| 班戈县| 邢台市| 永顺县| 正宁县| 高阳县| 丘北县| 宁海县| 华容县| 宾川县| 宿松县| 务川| 化州市| 普陀区| 安顺市| 吕梁市| 班戈县| 积石山| 涪陵区| 海宁市| 永吉县| 灵山县| 渭源县| 涿州市| 论坛| 延寿县| 湘西| 西城区| 新巴尔虎左旗| 营口市| 富源县| 安陆市| 宜城市| 东阳市| 天气| 梁山县| 宽甸| 义乌市| 区。| 达孜县|