Go語言學習04—變數、常量
變數和常量是程式設計中必不可少的部分,也是很好理解的一部分。
0x01 變數概述
程式裡面為什麼要有變數?人為什麼要有名字?為了方便。
記憶體地址4GB,0~2的32次方,根本記不住記憶體地址
變數的來歷
程式執行過程中的資料都是儲存在記憶體中,我們想要在程式碼中操作某個資料時就需要去記憶體上找到這個變數,但是如果我們直接在程式碼中通過記憶體地址去操作變數的話,程式碼的可讀性會非常差而且還容易出錯,所以我們就利用變數將這個資料的記憶體地址儲存起來,以後直接通過這個變數就能找到記憶體上對應的資料了。
變數型別
變數(Variable)的功能是儲存資料。不同的變數儲存的資料型別可能會不一樣。經過半個多世紀的發展,程式語言已經基本形成了一套固定的型別,常見變數的資料型別有:整型、浮點型、布林型等。
Go語言中的每一個變數都有自己的型別,並且變數必須經過宣告才能開始使用。
0x02 變數宣告方式
Go語言中的變數必須聲明後才能使用,同一作用域內不支援重複宣告。 並且Go語言的變數聲明後必須使用。
標準宣告
Go語言的變數宣告格式為:
var 變數名 變數型別
變數宣告以關鍵字var
開頭,變數型別放在變數的後面,行尾無需分號。 舉個例子:
var name string
var age int
var isOk bool
批量宣告
每宣告一個變數就需要寫var
關鍵字會比較繁瑣,go語言中還支援批量變數宣告:
var ( a string b int c bool d float32 )
推導宣告
有時候我們會將變數的型別省略,這個時候編譯器會根據等號右邊的值來推導變數的型別完成初始化。
var name = "Q1mi"
var age = 18
簡短 / 短變數宣告
在函式內部,可以使用更簡略的 :=
方式宣告並初始化變數。
package main
import (
"fmt"
)
// 全域性變數m
var m = 100
func main() {
n := 10
m := 200 // 此處宣告區域性變數m
fmt.Println(m, n)
}
特殊——匿名 / 啞元變數
在使用多重賦值時,如果想要忽略某個值,可以使用匿名變數(anonymous variable)
。 匿名變數用一個下劃線_
說的簡單點,假設一個函式返回值有兩個,我只想要一個,另一個怎麼辦?不想要他了,就可以用_
來賦值,來表示。例如:
func foo() (int, string) {
return 10, "Q1mi"
}
func main() {
x, _ := foo()
_, y := foo()
fmt.Println("x=", x)
fmt.Println("y=", y)
}
匿名變數不佔用名稱空間,不會分配記憶體,所以匿名變數之間不存在重複宣告。 (在Lua
等程式語言裡,匿名變數也被叫做啞元變數。)
思考一下,為什麼要有呢?因為Go語言中,宣告的函式不使用就會報錯。
注意事項:
- 函式外的每個語句都必須以關鍵字開始(var、const、func等)
:=
不能使用在函式外。_
多用於佔位,表示忽略值。
0x02 重點總結
1、全域性變數推薦使用批量宣告;函式體區域性變數推薦短變數宣告。
2、變數必須要宣告,聲明後必須要使用,否則無法編譯。
3、Println列印後自帶一個換行;Print普通列印;Printf需要有佔位符的配合。
4、同一個作用域中不能重複宣告;不同作用域中不建議重複宣告變數。
5、作用域暫時簡單理解為一對{}中就是一個作用域。
0x03 練習一
你會發現當我們儲存時,會自動給我們格式化。這是因為有外掛,實際上這個外掛用的是這條命令
go fmt main.go
package main
import "fmt"
//Go語言中推薦使用小駝峰式命名
// var student_name string 下劃線
// var studentName string 小駝峰,第二個單詞首字母大寫,推薦!
// var StudentName string 大駝峰,單詞首字母都大寫
//宣告變數
// var name string
// var age int
// var isok bool
//批量宣告變數,變數聲明後值為空
var (
name string // ""
age int // 0
isok bool // false
)
func main() {
name = "理想"
age = 16
isok = true
//Go語言中非全域性變數宣告必須要使用,不使用就編譯不過去,會變黃顏色。是為了減少空間
fmt.Println(age) //列印完指定的內容後,在後面加個換行
fmt.Print(isok) //在終端中輸出列印的內容
fmt.Println() //快捷列印一個空行,因為Println預設後面加個換行
fmt.Printf("name:%s\n", name) //%s:佔位符,使用name這個變數的值去替換佔位符,就是找個人先幫我頂著,等我辦完事兒就我就過來了
fmt.Print("Do you love me?")
//宣告變數的同時賦值,不推薦
//var s1 string = "whoami"
//變數宣告賦值,型別推導,根據賦值推導變數型別
//var myname = "sukusec301"
//簡短變數宣告,等同於var age = 18。必須在函式體裡面使用,不能在全域性使用
//age := 18
//age := 19,同一個作用域{}中不能重複宣告同名的變數
//匿名變數是一個特殊的變數:_後面學了函式在說
}
0x04 常量
比如一些錯誤程式碼,其實就是常量,大家都能看懂的程式碼
常量通常定義在全域性
相對於變數,常量是恆定不變的值,多用於定義程式執行期間不會改變的那些值。 常量的宣告和變數宣告非常類似,只是把var
換成了const
,常量在定義的時候必須賦值。
const pi = 3.1415
const e = 2.7182
聲明瞭pi
和e
這兩個常量之後,在整個程式執行期間它們的值都不能再發生變化了。
多個常量也可以一起宣告:
const (
pi = 3.1415
e = 2.7182
)
const同時宣告多個常量時,如果省略了值則表示和上面一行的值相同。 例如:
const (
n1 = 100
n2
n3
)
上面示例中,常量n1
、n2
、n3
的值都是100。
0x05 iota
iota
是go語言的常量計數器,只能在常量的表示式中使用。
iota
在const關鍵字出現時將被重置為0。const中每新增一行常量宣告將使iota
計數一次(iota可理解為const語句塊中的行索引)。 使用iota能簡化定義,在定義列舉時很有用。
舉個例子:
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
幾個常見的iota
示例
使用_
跳過某些值
const (
n1 = iota //0
n2 //1
_
n4 //3
)
iota
宣告中間插隊
const (
n1 = iota //0
n2 = 100 //100
n3 = iota //2
n4 //3
)
const n5 = iota //0
多個常量宣告在一行
const (
d1,d2 = iota+1,iota+2 //d1:1 d2:2
d3,d4 = iota+1,iota+2 //d3:2 d3:4
)
定義數量級(重點)
比方說我們百度網盤,充個會員,就會給你加多少多少T。那麼數量級肯定就是一個常量。
(這裡的<<
表示左移操作是位運算子的一種,1<<10
表示將1的二進位制表示向左移10位,也就是由1
變成了10000000000
,也就是十進位制的1024。同理2<<2
表示將2的二進位制表示向左移2位,也就是由10
變成了1000
,也就是十進位制的8。)
package main
import "fmt"
func main(){
const (
_ = iota #見到_,就說“扔了”就行,那麼這裡就是把iota扔了,因為根本不想用到iota,在後面就取消了iota
KB = 1 << (10 * iota)#1向左移動10位
MB = 1 << (10 * iota)#1向左移動10*(1+1)=20位
GB = 1 << (10 * iota)
TB = 1 << (10 * iota)
PB = 1 << (10 * iota)
)
fmt.Println("KB=", KB)
fmt.Println("MB=", MB)
fmt.Println("GB=", GB)
fmt.Println("TB=", TB)
fmt.Println("PB=", PB)
}
多個iota
定義在一行,再次強調,變數每增加一行,iota
才會自增1
const (
a, b = iota + 1, iota + 2 //1,2
c, d //2,3 這行即c, d = iota+1, iota+2,而iota在這行起始值為1
e, f //3,4 同上,只不過iota在這行起始為2
)
總結,iota=常量行數-1
常量總結
1、常量一般定義在全域性
2、常量定義之後,不能修改,在程式執行期間不能變化
3、批量宣告中,若下方常量沒有寫值,那麼就是和上方的常量值一樣。
4、iota可以發揮想象力靈活使用