變量來源于數(shù)學(xué),是計算機語言中能儲存計算結(jié)果或能表示值的抽象概念。變量可以通過變量名訪問。
Go 語言變量名由字母、數(shù)字、下劃線組成,其中首個字母不能為數(shù)字。
聲明變量的一般形式是使用 var 關(guān)鍵字:
var identifier type
第一種,指定變量類型,聲明后若不賦值,使用默認值。
var v_name v_type v_name = value
第二種,根據(jù)值自行判定變量類型。
var v_name = value
第三種,省略var, 注意 :=左側(cè)的變量不應(yīng)該是已經(jīng)聲明過的,否則會導(dǎo)致編譯錯誤。
v_name := value
// 例如
var a int = 10
var b = 10
c := 10
實例如下:
package main
var a = "w3cschoolW3Cschool教程"
var b string = "w3cschool.cn"
var c bool
func main(){
println(a, b, c)
}
以上實例執(zhí)行結(jié)果為:
w3cschoolW3Cschool教程 w3cschool.cn false
//類型相同多個變量, 非全局變量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 //和python很像,不需要顯示聲明類型,自動推斷
vname1, vname2, vname3 := v1, v2, v3 // 短變量聲明,僅適用于函數(shù)或方法內(nèi)部,多個變量一起聲明時,左側(cè)至少有一個未聲明過的變量,否則編譯錯誤,已聲明過的變量會退化為賦值
//類型不同多個變量, 全局變量, 局部變量不能使用這種方式
var (
vname1 v_type1
vname2 v_type2
)
實例如下:
package main
var x, y int
var (
a int
b bool
)
var c, d int = 1, 2
var e, f = 123, "hello"
//這種不帶聲明格式的只能在函數(shù)體中出現(xiàn)
//g, h := 123, "hello"
func main(){
g, h := 123, "hello"
println(x, y, a, b, c, d, e, f, g, h)
}
以上實例執(zhí)行結(jié)果為:
0 0 0 false 1 2 123 hello 123 hello
所有像 int、float、bool 和 string 這些基本類型都屬于值類型,使用這些類型的變量直接指向存在內(nèi)存中的值:
當使用等號 =
將一個變量的值賦值給另一個變量時,如:j = i
,實際上是在內(nèi)存中將 i 的值進行了拷貝:
你可以通過 &i 來獲取變量 i 的內(nèi)存地址,例如:0xf840000040(每次的地址都可能不一樣)。值類型的變量的值存儲在棧中。
內(nèi)存地址會根據(jù)機器的不同而有所不同,甚至相同的程序在不同的機器上執(zhí)行后也會有不同的內(nèi)存地址。因為每臺機器可能有不同的存儲器布局,并且位置分配也可能不同。
更復(fù)雜的數(shù)據(jù)通常會需要使用多個值,這些數(shù)據(jù)一般使用引用類型保存。
一個引用類型的變量 r1 存儲的是 r1 的值所在的內(nèi)存地址(數(shù)字),或內(nèi)存地址中第一個值所在的位置。
這個內(nèi)存地址為稱之為指針,這個指針實際上也被存在另外的某一個值中。
同一個引用類型的指針指向的多個值可以是在連續(xù)的內(nèi)存地址中(內(nèi)存布局是連續(xù)的),這也是計算效率最高的一種存儲形式;也可以將這些值分散存放在內(nèi)存中,每個值都指示了下一個值所在的內(nèi)存地址。
當使用賦值語句 r2 = r1 時,只有引用(地址)被復(fù)制。
如果 r1 的值被改變了,那么這個值的所有引用都會指向被修改后的內(nèi)容,在這個例子中,r2 也會受到影響。
我們知道可以在變量的初始化時省略變量的類型而由系統(tǒng)自動推斷,聲明語句寫上 var 關(guān)鍵字其實是顯得有些多余了,因此我們可以將它們簡寫為 a := 50 或 b := false。
a 和 b 的類型(int 和 bool)將由編譯器自動推斷。
這是使用變量的首選形式,但是它只能被用在函數(shù)體內(nèi),而不可以用于全局變量的聲明與賦值。使用操作符 := 可以高效地創(chuàng)建一個新的變量,稱之為初始化聲明。
如果在相同的代碼塊中,我們不可以再次對于相同名稱的變量使用初始化聲明,例如:a := 20 就是不被允許的(因為在前文中已經(jīng)聲明了a:=50),編譯器會提示錯誤 no new variables on left side of :=,但是 a = 20 是可以的,因為這是給相同的變量賦予一個新的值。
如果你在定義變量 a 之前使用它,則會得到編譯錯誤 undefined: a。
如果你聲明了一個局部變量卻沒有在相同的代碼塊中使用它,同樣會得到編譯錯誤,例如下面這個例子當中的變量 a:
func main() {
var a string = "abc"
fmt.Println("hello, world")
}
嘗試編譯這段代碼將得到錯誤 a declared but not used。
此外,單純地給 a 賦值也是不夠的,這個值必須被使用,所以使用
fmt.Println("hello, world", a)
會移除錯誤。
但是全局變量是允許聲明但不使用。
同一類型的多個變量可以聲明在同一行,如:
var a, b, c int
多變量可以在同一行進行賦值,如:
a, b, c = 5, 7, "abc"
上面這行假設(shè)了變量 a,b 和 c 都已經(jīng)被聲明,否則的話應(yīng)該這樣使用:
a, b, c := 5, 7, "abc"
右邊的這些值以相同的順序賦值給左邊的變量,所以 a 的值是 5, b 的值是 7,c 的值是 "abc"。
這被稱為 并行 或 同時 賦值。
如果你想要交換兩個變量的值,則可以簡單地使用 a, b = b, a。
空白標識符 _ 也被用于拋棄值,如值 5 在:_, b = 5, 7 中被拋棄。
_ 實際上是一個只寫變量,你不能得到它的值。這樣做是因為 Go 語言中你必須使用所有被聲明的變量,但有時你并不需要使用從一個函數(shù)得到的所有返回值。
并行賦值也被用于當一個函數(shù)返回多個返回值時,比如這里的 val 和錯誤 err 是通過調(diào)用 Func1 函數(shù)同時得到:val, err = Func1(var1)。
更多建議: