#變量和常量定義
現在我們討論一下Go語言的變量定義。
**變量定義**
所謂的變量就是一個擁有指定`名稱`和`類型`的`數據存儲位置`。
在上面我們使用過變量的定義,現在我們來仔細看一個例子。
package main
import (
"fmt"
)
func main() {
var x string = "hello world"
fmt.Println(x)
}
變量的定義首先使用`var`關鍵字,然后指定變量的名稱`x`,再指定變量的類型`string`,在本例中,還對變量`x`進行了賦值,然后在命令行輸出該變量。Go這種變量定義的方式和其他的語言有些不同,但是在使用的過程中,你會逐漸喜歡的。當然上面的變量定義方式還可以如下,即先定義變量,再賦值。
package main
import (
"fmt"
)
func main() {
var x string
x = "hello world"
fmt.Println(x)
}
或者是直接賦值,讓Go語言推斷變量的類型。如下:
package main
import (
"fmt"
)
func main() {
var x = "hello world"
fmt.Println(x)
}
當然,上面變量的定義還有一種`快捷方式`。如果你知道變量的初始值,完全可以像下面這樣定義變量,完全讓`Go來推斷語言的類型`。這種定義的方式連關鍵字`var`都省略掉了。
package main
import (
"fmt"
)
func main() {
x := "hello world"
fmt.Println(x)
}
注意:上面這種使用`:=`方式定義變量的方式`只能用在函數內部`。
package main
import (
"fmt"
)
x:="hello world"
func main() {
y := 10
fmt.Println(x)
fmt.Println(y)
}
對于上面的變量定義x是無效的。會導致編譯錯誤:
./test_var_quick.go:7: non-declaration statement outside function body
不過我們對上面的例子做下修改,比如這樣是可以的。也就是使用var關鍵字定義的時候,如果給出初始值,就不需要顯式指定變量類型。
package main
import (
"fmt"
)
var x = "hello world"
func main() {
y := 10
fmt.Println(x)
fmt.Println(y)
}
`變量`之所以稱為變量,就是因為`它們的值在程序運行過程中可以發生變化`,但是`它們的變量類型是無法改變的`。因為`Go語言是靜態語言`,并`不支持`程序運行過程中`變量類型發生變化`。比如如果你強行將一個字符串值賦值給定義為int的變量,那么會發生編譯錯誤。即使是強制類型轉換也是不可以的。`強制類型轉換只支持同類的變量類型`。比如數值類型之間強制轉換。
下面我們看幾個例子:
package main
import (
"fmt"
)
func main() {
var x string = "hello world"
fmt.Println(x)
x = "i love go language"
fmt.Println(x)
}
本例子演示變量的值在程序運行過程中發生變化,結果輸出為
hello world
i love go language
我們嘗試不同類型的變量之間轉換
package main
import (
"fmt"
)
func main() {
var x string = "hello world"
fmt.Println(x)
x = 11
fmt.Println(x)
}
在本例子中,如果試圖將一個數值賦予字符串變量x,那么會發生錯誤:
./test_var.go:10: cannot use 11 (type int) as type string in assignment
上面的意思就是無法將整型數值11當作字符串賦予給字符串變量。
但是同類的變量之間是可以強制轉換的,如浮點型和整型之間的轉換。
package main
import (
"fmt"
)
func main() {
var x float64 = 32.35
fmt.Println(x)
fmt.Println(int(x))
}
輸出的結果為
32.35
32
**變量命名**
上面我們看了一些變量的使用方法,那么定義一個變量名稱,有哪些要求呢?
這里我們要注意,`Go的變量名稱必須以字母或下劃線(_)開頭,后面可以跟字母,數字,或者下劃線(_)`。除此之外,Go語言并不關心你如何定義變量。我們通用的做法是定義一個用戶友好的變量。假設你需要定義一個狗狗的年齡,那么使用dog_age作為變量名稱要好于用x來定義變量。
**變量作用域**
現在我們再來討論一下變量的作用域。所謂作用域就是可以有效訪問變量的區域。比如很簡單的,你不可能在一個函數func_a里面訪問另一個函數func_b里面定義的局部變量x。所以變量的作用域目前分為兩類,一個是`全局變量`,另一個是`局部變量`。下面我們看個全局變量的例子:
package main
import (
"fmt"
)
var x string = "hello world"
func main() {
fmt.Println(x)
}
這里變量x定義在main函數之外,但是main函數仍然可以訪問x。全局變量的作用域是該包中所有的函數。
package main
import (
"fmt"
)
var x string = "hello world"
func change() {
x = "i love go"
}
func main() {
fmt.Println(x)
change()
fmt.Println(x)
}
在上面的例子用,我們用了change函數改變了x的值。輸出結果如下:
hello world
i love go
我們再看一下局部變量的例子。
package main
import (
"fmt"
)
func change() {
x := "i love go"
}
func main() {
fmt.Println(x)
}
該例子中main函數試圖訪問change函數中定義的局部變量x,結果發生了下面的錯誤(未定義的變量x):
./test_var.go:11: undefined: x
**常量**
Go語言也支持常量定義。所謂`常量就是在程序運行過程中保持值不變的變量定義`。常量的定義和變量類似,只是用`const`關鍵字替換了var關鍵字,另外常量在定義的時候`必須有初始值`。
package main
import (
"fmt"
)
func main() {
const x string = "hello world"
const y = "hello world"
fmt.Println(x)
fmt.Println(y)
}
這里有一點需要注意,變量定義的類型推斷方式`:=`不能夠用來定義常量。因為常量的值是在編譯的時候就已經確定的,但是變量的值則是運行的時候才使用的。這樣常量定義就無法使用變量類型推斷的方式了。
常量的值在運行過程中是無法改變的,強制改變常量的值是無效的。
package main
import (
"fmt"
)
func main() {
const x string = "hello world"
fmt.Println(x)
x = "i love go language"
fmt.Println(x)
}
比如上面的例子就會報錯
./test_var.go:10: cannot assign to x
我們再看一個Go包math里面定義的常量Pi,用它來求圓的面積。
package main
import (
"fmt"
"math"
)
func main() {
var radius float64 = 10
var area = math.Pow(radius, 2) * math.Pi
fmt.Println(area)
}
**多變量或常量定義**
Go還提供了一種`同時定義多個變量或者常量`的快捷方式。
package main
import (
"fmt"
)
func main() {
var (
a int = 10
b float64 = 32.45
c bool = true
)
const (
Pi float64 = 3.14
True bool = true
)
fmt.Println(a, b, c)
fmt.Println(Pi, True)
}