Go 語言變數
變數來自數學,是電腦語言中能儲存計算結果或能表示值抽象概念。變數可以透過變數名存取。
Go 語言變數名由字母、數字、底線組成,其中首個字母不能為數字。
宣告變數的一般形式是使用 var 關鍵字:
var identifier type
變數宣告
第一種,指定變數類型,宣告後若不賦值,使用預設值。
var v_name v_type v_name = value
第二種,根據值自行判定變數類型。
var v_name = value
第三種,省略var, 注意 :=左邊的變數不應該是已經宣告過的,否則會導致編譯錯誤。
v_name := value // 例如 var a int = 10 var b = 10 c : = 10
實例如下:
package main var a = "w3cschoolphp中文网" var b string = "w3cschool.cc" var c bool func main(){ println(a, b, c) }
以上實例執行結果為:
w3cschoolphp中文网 w3cschool.cc 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 //出现在:=左侧的变量不应该是已经被声明过的,否则会导致编译错误 // 这种因式分解关键字的写法一般用于声明全局变量 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" //这种不带声明格式的只能在函数体中出现 //g, h := 123, "hello" func main(){ g, h := 123, "hello" println(x, y, a, b, c, d, e, f, g, h) }
以上實例執行結果為:
0 0 0 false 1 2 123 hello 123 hello
值型別與參考型別
所有像int、float、bool 和string 這些基本型別都屬於值型,使用這些型別
所有像int、float、bool 和string 這些基本型別都屬於值型,使用這些型別所有像是int指向存在記憶體中的值:
當使用等號
j = i
,實際上是在記憶體中將i 的值進行了拷貝:你可以透過&i 來取得變數i 的記憶體位址,例如:0xf840000040(每次的位址都可能不一樣)。值類型的變數的值儲存在堆疊中。
記憶體位址會根據機器的不同而有所不同,甚至相同的程式在不同的機器上執行後也會有不同的記憶體位址。因為每台機器可能有不同的記憶體佈局,而且位置分配也可能不同。
更複雜的資料通常會需要使用多個字,這些資料一般使用引用類型保存。
一個引用型別的變數 r1 儲存的是 r1 的值所在的記憶體位址(數字),或記憶體位址中第一個字的位置。這個記憶體位址為稱為指針,這個指標其實也被存在另外的某一個字。
同一個引用類型的指標指向的多個字可以是在連續的記憶體位址中(記憶體佈局是連續的),這也是計算效率最高的一種儲存形式;也可以將這些字分散存放在記憶體中,每個字都指示了下一個字所在的記憶體位址。
###當使用賦值語句 r2 = r1 時,只有引用(位址)被複製。 ######如果 r1 的值被改變了,那麼這個值的所有參考都會指向被修改後的內容,在這個例子中,r2 也會受到影響。 ###簡短形式,使用:= 賦值運算子
我們知道可以在變數的初始化時省略變數的型別而由系統自動推斷,宣告語句寫上var 關鍵字其實是顯得有些多餘了,因此我們可以將它們簡寫為a := 50 或b := false。
a 和 b 的型別(int 和 bool)將由編譯器自動推斷。
這是使用變數的首選形式,但是它只能用在函數體內,而不可以用於全域變數的宣告與賦值。使用操作符 := 可以有效率地建立一個新的變量,稱之為初始化聲明。
注意事項
如果在相同的程式碼區塊中,我們不可以再次對於相同名稱的變數使用初始化聲明,例如:a := 20 就是不被允許的,編譯器會提示錯誤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 and not used。
此外,單純地給 a 賦值也是不夠的,這個值必須被使用,所以使用
fmt.Println("hello, world", a)
會移除錯誤。
但是全域變數是允許宣告但不使用。
>同一類型的多個變數可以宣告在同一行,如:
var a, b, c int
多變數可以在同一行進行賦值,如:
a, b, c = 5, 7, "abc"
上面這行假設了變數a,b 和c 都已經被聲明,否則的話應該這樣使用:
a, b, c := 5, 7, "abc"
右邊的這些值以相同的順序賦值給左邊的變量,所以a 的值是5, b 的值是7,c 的值是"abc"。
這稱為 並行 或 同時 賦值。
如果你想要交換兩個變數的值,可以簡單地使用 a, b = b, a。
空白標識符 _ 也被用來拋棄值,如值 5 在:_, b = 5, 7 中被拋棄。
_ 其實是一個只寫變量,你不能得到它的值。這樣做是因為 Go 語言中你必須使用所有被宣告的變量,但有時你並不需要使用從一個函數得到的所有回傳值。
平行賦值也被用來當一個函數傳回多個回傳值時,例如這裡的 val 和錯誤 err 是透過呼叫 Func1 函數同時得到:val, err = Func1(var1)。