書名: 深入淺出Go語言核心編程作者名: 張朝明 李奕鋒 甘海彬本章字數: 2919字更新時間: 2024-12-24 10:23:13
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)完成引用。而鏈接階段處于編譯階段之后,因此,編譯器無法識別全局變量的引用情況,也就不會出現編譯錯誤。
- 多媒體CAI課件設計與制作導論(第二版)
- ClickHouse性能之巔:從架構設計解讀性能之謎
- C++案例趣學
- Cross-platform Desktop Application Development:Electron,Node,NW.js,and React
- INSTANT Weka How-to
- UML+OOPC嵌入式C語言開發精講
- SAP BusinessObjects Dashboards 4.1 Cookbook
- Learning JavaScript Data Structures and Algorithms
- Microsoft Azure Storage Essentials
- Learning Apache Karaf
- Unity 2018 Augmented Reality Projects
- IDA Pro權威指南(第2版)
- Exploring SE for Android
- Unity 5.X從入門到精通
- Flask Web開發:基于Python的Web應用開發實戰(第2版)