變量
聲明變量格式:
var var_name var_type
變量在聲明時會自動初始化:
數字: 0
string: ""
bool: false
引用類型: nil
結構體: 所有元素或成員的零值
var
通常用於與初始化表達式類型不一致的局部變量、后面再賦值或初始值不重要的情況,否則可以使用更加簡便的短變量聲明
短變量聲明
短變量聲明更加簡便,變量類型會通過變量初始值自動判斷
短變量聲明用於局部變量聲明,最少聲明一個變量
a := 1
多變量賦值
多個變量可以在一起賦值
var a, b, c int
d, e, f := 1, 2, "I'm F"
var(
a = 1
b int
)
局部變量
局部變量聲明就必須使用,否則編譯時會報錯
// 可以先聲明,再初始化
var a int
a = 1
// 可以在聲明的同時進行初始化
var a int = 1
// Go 可以在初始化的時候自動判斷變量類型,所以 int 可以省略
var a = 1
// var a = 1 的簡略寫法,同樣會自動判斷
a := 1
全局變量
全局變量聲明后可以不使用,編譯時不會報錯
全局變量首字母必須大寫,否則從其他包中就無法訪問到
由於所有語句必須在函數中,所以無法通過 :=
聲明全局變量,全局變量只能通過 var
進行聲明
var A int = 1
或者可以通過初始化函數對其進行初始化
var A int
func init() {
A = 3
}
只寫變量 _
由於 Go 中不允許出現局部變量聲明后不使用的情況,但是有時會出現需要接收一個值,但是之后又不會用到
如果直接聲明一個變量去接收,由於之后沒有用到,所以編譯無法通過,這時就可以使用只寫變量 _
來接收之后用不到的值
變量作用域
函數內聲明的變量是局部變量,只在函數內有效
函數外部聲明的是全局變量,如果首字母小寫,只能在當前包中訪問;如果首字母大寫,可以在其他包中訪問到
變量的生命周期
變量的生命周期由變量是否可達決定
包級別變量的生命周期是整個程序的執行時間
局部變量的生命周期則不一定
逃逸
示例:
var global *int
func foo() {
x := 1
global = &x
}
雖然 x 是局部變量,但是由於 global 引用了 x,所以即使函數返回,x 仍然可達,不會被回收,這時 x 從 foo 中逃逸
常量
常量在編譯時就會確定,之后無法修改
常量聲明和變量相似,但是聲明時必須要有值
格式:
const const_name const_type = value
變量的類型可以省略
多行聲明:
const(
blog = "cnblogs.com/dbf-/"
Pi = 3.14159
)
計算表達式
常量可以使用計算表達式,但是只能用內置的常量計算表達式
const(
a = "123"
length = len(a)
)
自動填充
在給第一個常量賦值之后,如果之后的沒有賦值,就會自動賦為上面的值
常量生成器 (iota)
聲明常量時可以通過 iota
實現自增
示例:
package main
import "fmt"
const(
a = iota
b = "string"
c
d = iota
e
)
const(
f = iota
g
h
)
func main() {
fmt.Println(a, b, c, d, e)
fmt.Println(f, g, h)
}
輸出結果:
0 string string 3 4
0 1 2
在一個 const
中使用 iota
后,就會自動從第一個開始計數,為之后每一個常量分配一個值,雖然中間被其他的賦值打斷,但是計數器仍然在工作
在一個新的 const
中,計數器會重新計數
值類型
基本數據類型:int、float、bool、string、struct 等都是值類型
值類型中儲存的就是值
內存通常在棧中分配
引用類型
指針、切片、map、chan 等都是引用類型
引用類型中儲存的是內存地址,內存地址指向的才是值
內存通常在堆中分配