《快學 Go 語言》第 2 課 —— 變數什麼的最討厭了
任何一門語言裡面最基礎的莫過於變數了。如果把記憶體比喻成一格一格整齊排列的儲物箱,那麼變數就是每個儲物箱的標識,我們透過變數來訪問計算機記憶體。沒有變數的程式對於人類來說是可怕的,需要我們用數字位置來定位記憶體的格子,人類極不擅長這樣的事。這就好比一歲半左右的幼兒還沒有學會很多名詞,只能用手來對物體指指點點來表達自己的喜好。變數讓程式邏輯有了豐富的表達形式。
定義變數的三種方式
Go 語言的變數定義有多種形式,我們先看最繁瑣的形式
package main
import "fmt"
func main() {
var s int = 42
fmt.Println(s)
}
-------------
42
注意到我們使用了 var 關鍵字,它就是用來顯式定義變數的。還注意到在變數名稱 s 後面宣告瞭變數的型別為整形 int,然後再給它賦上了一個初值 42。上面的變數定義可以簡化,將型別去掉,因為編譯器會自動推導變數型別,效果也是一樣的,如下
package main
import "fmt"
func main() {
var s = 42
fmt.Println(s)
}
---------------
42
更進一步,上面的變數定義還可以再一次簡化,去掉 var 關鍵字。
package main
import "fmt"
func main() {
s := 42
fmt.Println(s)
}
---------------
42
注意到賦值的等號變成了 :=,它表示變數的「自動型別推導 + 賦值」。
這三種變數定義方式都是可行的,各有其優缺點。可讀性最強的是第一種,寫起來最方便的是第三種,第二種是介於兩者之間的形式。
型別是變數身份的象徵,如果一個變數不那麼在乎自己的身份,那在形式上就可以隨意一些。var 的意思就是告訴讀者「我很重要,你要注意」,:= 的意思是告訴讀者「我很隨意,別把我當回事」。var 再帶上顯式的型別資訊是為了方便讀者快速識別變數的身份。
如果一個變數很重要,建議使用第一種顯式宣告型別的方式來定義,比如全域性變數的定義就比較偏好第一種定義方式。如果要使用一個不那麼重要的區域性變數,就可以使用第三種。比如迴圈下標變數
for i:=0; i<10; i++ {
doSomething()
}
那第二種方式能不能用在上面的迴圈下標中呢,答案是不可以,你無法將 var 關鍵字直接寫進迴圈條件中的初始化語句中,而必須提前宣告變數,像下面這樣,這時就很明顯不如簡寫的形式了
var i = 0
for ; i<10; i++ {
doSomething()
}
如果在第一種宣告變數的時候不賦初值,編譯器就會自動賦予相應型別的「零值」,不同型別的零值不盡相同,比如字串的零值不是 nil,而是空串,整形的零值就是 0 ,布林型別的零值是 false。
package main
import "fmt"
func main() {
var i int
fmt.Println(i)
}
-----------
0
全域性變數和區域性變數
上面我們在程式碼例子中編寫的變數都是區域性變數,它定義在函式內部,函式呼叫結束它就消亡了。與之對應的是全域性變數,在程式執行期間,它一直存在,它定義在函式外面。
package main
import "fmt"
var globali int = 24
func main() {
var locali int = 42
fmt.Println(globali, locali)
}
---------------
24 42
如果全域性變數的首字母大寫,那麼它就是公開的全域性變數。如果全域性變數的首字母小寫,那麼它就是內部的全域性變數。內部的全域性變數只有當前包內的程式碼可以訪問,外面包的程式碼是不能看見的。
學過 C 語言的同學可能會問,Go 語言裡有沒有靜態變數呢?答案是沒有。
變數與常量
Go 語言還提供了常量關鍵字 const,用於定義常量。常量可以是全域性常量也可以是區域性常量。你不可以修改常量,否則編譯器會抱怨。常量必須初始化,因為它無法二次賦值。全域性常量的大小寫規則和變數是一致的。
package main
import "fmt"
const globali int = 24
func main() {
const locali int = 42
fmt.Println(globali, locali)
}
指標型別
Go 語言被稱為網際網路時代的 C 語言,它延續使用了 C 語言的指標型別。
package main
import "fmt"
func main() {
var value int = 42
var pointer *int = &value
fmt.Println(pointer, *pointer)
}
--------------
0xc4200160a0 42
我們又看到了久違的指標符號 * 和取地址符 &,在功能和使用上同 C 語言幾乎一摸一樣。同 C 語言一樣,指標還支援二級指標,三級指標,只不過在日常應用中,很少遇到。
package main
import "fmt"
func main() {
var value int = 42
var p1 *int = &value
var p2 **int = &p1
var p3 ***int = &p2
fmt.Println(p1, p2, p3)
fmt.Println(*p1, **p2, ***p3)
}
----------
0xc4200160a0 0xc42000c028 0xc42000c030
42 42 42
指標變數本質上就是一個整型變數,裡面儲存的值是另一個變數記憶體的地址。* 和 & 符號都只是它的語法糖,是用來在形式上方便使用和理解指標的。* 運算子存在兩次記憶體讀寫,第一次獲取指標變數的值,也就是記憶體地址,然後再去拿這個記憶體地址所在的變數內容。
如果普通的變數是一個儲物箱,那麼指標變數就是另一個儲物箱,這個儲物箱裡存放了普通變數所在儲物箱的鑰匙。透過多級指標來讀取變數值就好比在玩一個解密遊戲。
Go 語言基礎型別大全
Go 語言定義了非常豐富的基礎型別,下面我列舉了所有的基礎資料型別。
package main
import "fmt"
func main() {
// 有符號整數,可以表示正負
var a int8 = 1 // 1 位元組
var b int16 = 2 // 2 位元組
var c int32 = 3 // 4 位元組
var d int64 = 4 // 8 位元組
fmt.Println(a, b, c, d)
// 無符號整數,只能表示非負數
var ua uint8 = 1
var ub uint16 = 2
var uc uint32 = 3
var ud uint64 = 4
fmt.Println(ua, ub, uc, ud)
// int 型別,在32位機器上佔4個位元組,在64位機器上佔8個位元組
var e int = 5
var ue uint = 5
fmt.Println(e, ue)
// bool 型別
var f bool = true
fmt.Println(f)
// 位元組型別
var j byte = 'a'
fmt.Println(j)
// 字串型別
var g string = "abcdefg"
fmt.Println(g)
// 浮點數
var h float32 = 3.14
var i float64 = 3.141592653
fmt.Println(h, i)
}
-------------
1 2 3 4
1 2 3 4
5 5
true
abcdefg
3.14 3.141592653
97
還有另外幾個不常用的資料型別,讀者可以暫不理會。
複數型別 complex64 和 complex128
unicode字元型別 rune
uintptr 指標型別
複數型別用於科學計算,平時基本上用不上。rune 和 uintptr 的用法在後續文章中會詳細講解。簡單一點說 rune 和 byte 的關係就好比 Python 裡面的 unicode 和 byte 、Java 語言裡面的 char 和 byte 。uintptr 相當於 C 語言裡面的 void* 指標型別。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31561269/viewspace-2220636/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 《快學 Go 語言》第 2 課 —— 變數基礎Go變數
- 《快學 Go 語言》第 7 課 —— 字串Go字串
- 《快學 Go 語言》第 6 課 —— 字典Go
- 《快學 Go 語言》第 14 課 —— 反射Go反射
- 《快學 Go 語言》第 12 課 —— 通道Go
- 《快學 Go 語言》第 9 課 —— 介面Go
- 《快學 Go 語言》第 15 課 —— 反射Go反射
- 《快學 Go 語言》第 5 課 —— 神奇的切片Go
- 《快學 Go 語言》第 14 課 —— 魔術變性指標Go指標
- 《快學 Go 語言》第 1 課 —— Hello WorldGo
- 《快學 Go 語言》第 5 課 —— 靈活的切片Go
- 《快學 Go 語言》第 4 課 —— 低調的陣列Go陣列
- 《快學 Go 語言》第 7 課 —— 誘人的烤串Go
- 《快學 Go 語言》第 12 課 —— 神秘的地下通道Go
- 《快學 Go 語言》第 3 課 —— 分支與迴圈Go
- 《快學 Go 語言》第 7 課 —— 冰糖葫蘆串Go
- 《快學 Go 語言》第 13 課 —— 併發與安全Go
- 《快學 Go 語言》第 16 課 —— 包管理 GOPATH 和 VendorGo
- 為什麼程式設計師會有最喜歡與最討厭的程式語言?(earthly)程式設計師
- 程式設計師為什麼討厭這些語言程式設計師
- 《快學 Go 語言》第 11 課 —— 千軍萬馬跑協程Go
- 最喜歡與最討厭的函數語言程式設計語言情緒排名 | Scalac.io函數程式設計
- 《快學 Go 語言》第 8 課 —— 程式大廈是如何構建起來的Go
- 初學Go語言 變數Go變數
- go語言變數Go變數
- Python與PHP的對決:誰是工程師最喜歡和最討厭的語言PythonPHP工程師
- GO語言————4.4 變數Go變數
- 為什麼那麼多人要學習go語言?go語言有什麼特點?Go
- 什麼是Go語言?Go語言有什麼特點?Go
- Go 1.21的2個語言變化Go
- go與其他語言有什麼區別?學習go語言怎麼樣Go
- go語言 變數的宣告與使用Go變數
- go培訓課程都學什麼?go語言框架學習:xorm框架知識介紹Go框架ORM
- go語言能做什麼Go
- 為什麼要學習Go語言呢?Go
- Go 語言入門教程:變數Go變數
- 為什麼我如此討厭scrums? - RedditScrum
- Go語言學習(3) - 變數與初始化Go變數