go--變量、常量、作用域
變量
變量可以通過變量名訪問。Go 語言變量名由字母、數(shù)字、下劃線組成,其中首個(gè)字符不能為數(shù)字。
聲明變量的一般形式是使用 var 關(guān)鍵字:
var 變量名 變量類型
也可以一次聲明多個(gè)變量
var 變量名1,變量名2 變量類型
package main
import "fmt"
func main() {
var a string = "zouzou" // 定義了個(gè)變量 a,類型為 string,值為 鄒鄒
fmt.Println(a)
var b, c int = 1, 2 // 定義了兩個(gè)變量 b 和 c,類型為 int,b 的值為 1,c 的值為 2
fmt.Println(b, c)
}
結(jié)果
zouzou
1 2
如果沒有初始化,則變量默認(rèn)為零值
零值就是變量沒有做初始化時(shí)系統(tǒng)默認(rèn)設(shè)置的值。
package main
import "fmt"
func main() {
// 聲明一個(gè)變量并初始化
var a = "zouzou"
fmt.Println(a)
// 沒有初始化就為零值
var b int
fmt.Println(b)
// bool 零值為 false
var c bool
fmt.Println(c)
}
結(jié)果
zouzou
0
false
零值的有
-
數(shù)值類型(包括complex64/128)為 0
-
布爾類型為 false
-
字符串為 ""(空字符串)
-
以下幾種類型為 nil:
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口
類型推導(dǎo)
如果聲明了一個(gè)變量,沒有聲明類型,會(huì)根據(jù)值進(jìn)行類型推導(dǎo)
package main
import "fmt"
func main() {
var d = true // 沒有聲明類型,會(huì)自動(dòng)推導(dǎo)
fmt.Println(d)
}
結(jié)果
true
如果變量已經(jīng)使用 var 聲明過了,再使用 := 聲明變量,就產(chǎn)生編譯錯(cuò)誤,格式
v_name := value
例如
var intVal int
intVal :=1 // 這時(shí)候會(huì)產(chǎn)生編譯錯(cuò)誤,因?yàn)?intVal 已經(jīng)聲明,不需要重新聲明
直接使用下面的語句即可:
intVal := 1 // 此時(shí)不會(huì)產(chǎn)生編譯錯(cuò)誤,因?yàn)橛新暶餍碌淖兞浚驗(yàn)?:= 是一個(gè)聲明語句
intVal := 1 相等于
var intVal int
intVal =1
可以將 var f string = "zouzou" 簡(jiǎn)寫為 f := "zouzou":
package main
import "fmt"
func main() {
f := "zouzou" // 等價(jià)于 var f string = "zouzou"
fmt.Println(f)
}
還有其他的聲明方式
package main
var x, y int
var ( // 這種因式分解關(guān)鍵字的寫法一般用于聲明全局變量
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)
}
使用 := 賦值操作符
我們知道可以在變量的初始化時(shí)省略變量的類型而由系統(tǒng)自動(dòng)推斷,聲明語句寫上 var 關(guān)鍵字其實(shí)是顯得有些多余了,因此我們可以將它們簡(jiǎn)寫為 a := 50 或 b := false。
a 和 b 的類型(int 和 bool)將由編譯器自動(dòng)推斷。
這是使用變量的首選形式,但是它只能被用在函數(shù)體內(nèi),而不可以用于全局變量的聲明與賦值。使用操作符 := 可以高效地創(chuàng)建一個(gè)新的變量,稱之為初始化聲明。
常量
常量是一個(gè)簡(jiǎn)單值的標(biāo)識(shí)符,在程序運(yùn)行時(shí),不會(huì)被修改的量。
常量中的數(shù)據(jù)類型只可以是布爾型、數(shù)字型(整數(shù)型、浮點(diǎn)型和復(fù)數(shù))和字符串型。
常量的定義格式:
const 常量名 [type] = value
你可以省略類型說明符 [type],因?yàn)榫幾g器可以根據(jù)變量的值來推斷其類型。
- 顯式類型定義:
const b string = "abc" - 隱式類型定義:
const b = "abc"
package main
import "fmt"
func main() {
const LENGTH int = 10 // 常量 LENGTH
const WIDTH int = 5 // 常量 WIDTH
var area int // 變量
const a, b, c = 1, false, "zou" //多重賦值
area = LENGTH * WIDTH
fmt.Printf("面積為 : %d", area)
println()
println(a, b, c)
}
結(jié)果
面積為 : 50
1 false zou
在常量組中,如果不指定類型和值,則和上一行的類型還有值都一樣
package main
import "fmt"
func main() {
// 常量組如果不指定類型和值,則和上一行的類型的值一樣
const (
x int = 10
y
a = "abc"
b
)
fmt.Print(x, y, a, b)
}
結(jié)果
10 10 abc abc
iota
- iota,特殊常量,可以認(rèn)為是一個(gè)可以被編譯器修改的常量。
- iota 只能在常量組中使用
- 不同的 const 塊中互相不影響
- 從第一行開始,每一行 iota 都會(huì)加 1
iota 可以被用作枚舉值:
const (
a = iota // iota = 0
b = iota // iota = 1,每一行 iota 加 1
c = iota // iota = 2,每一行 iota 加 1
)
第一個(gè) iota 等于 0,每當(dāng) iota 在新的一行被使用時(shí),它的值都會(huì)自動(dòng)加 1;所以 a=0, b=1, c=2 可以簡(jiǎn)寫為如下形式:
const (
a = iota
b
c
)
看下面的例子
package main
import "fmt"
func main() {
const (
a = iota // 0
b = 10 // iota = 1
c // 和上一行的值相等
d, e = iota, iota // iota = 3,所以 d、e 都等于 3
f = iota // iota = 4
)
fmt.Println(a, b, c, d, e, f)
}
結(jié)果
0 10 10 3 3 4
例子二
package main
import "fmt"
func main() {
const (
a = iota // 0
b // 1
c // 2
d = "ha" //獨(dú)立值,iota = 3
e //沒有值和上一行的值相等 "ha" iota = 4
f = 100 //iota = 5
g //沒有值和上一行的值相等 100 iota = 6
h = iota // 7,恢復(fù)計(jì)數(shù)
i // 8
)
fmt.Println(a, b, c, d, e, f, g, h, i)
}
輸出結(jié)果
0 1 2 ha ha 100 100 7 8
作用域
package main
import "fmt"
func main() {
name := "zouzou" // 只在當(dāng)前的 {} 里有效
fmt.Println(name)
if true {
fmt.Println(name)
age := 18 // 只在當(dāng)前的 {} 里有效
fmt.Println(age)
name := "鄒鄒"
fmt.Println(name)
}
println(name)
//fmt.Println(age) 錯(cuò)誤,因?yàn)?age 是局部變量
}
結(jié)果
zouzou
zouzou
18
鄒鄒
zouzou
- 全局變量,未寫在函數(shù)中的變量稱為全局變量;不可以使用
v1:=xx方式進(jìn)行簡(jiǎn)化;可以基于因式分解方式聲明多個(gè)變量; - 局部變量,編寫在 {} 里面的變量;可以使用任意方式簡(jiǎn)化;可以基于因式分解方式聲明多個(gè)變量;
package main
import "fmt"
// 全局變量(不能以省略的方式)
var school string = "北京大學(xué)" // 可以
//var school = "北京大學(xué)" // 可以
//school := "北京大學(xué)" // 不可以,不能簡(jiǎn)寫
var ( // 全局變量
v1 = 123
v2 = "你好"
v3 int
)
func main() {
name := "zouzou" // 局部變量
fmt.Println(name)
if true {
age := 18 // 局部變量
name := "鄒鄒" // 局部變量
fmt.Println(age)
fmt.Println(name)
}
fmt.Println(name)
fmt.Println(school)
fmt.Println(v1, v2, v3)
}
結(jié)果
zouzou
18
鄒鄒
zouzou
北京大學(xué)
123 你好 0
賦值與內(nèi)存相關(guān)
name := "zouzou"
如上代碼,定義了一個(gè)變量,會(huì)在內(nèi)存中開辟出一塊地址,賦值給變量 name

name := "zouzou"
nickname := name
如上如果定義了一個(gè)變量 name,在定義了一個(gè)變量 nickname,將 name 賦值給 nickname。在 go 中,會(huì)將 name 的拷貝一份,如下

package main
import "fmt"
func main() {
name := "zouzou"
nickName := name
fmt.Println(name, &name) // &name 是 name 變量的內(nèi)存地址
fmt.Println(nickName, &nickName) // &nickName 是 nickName 變量的內(nèi)存地址
}
結(jié)果
zouzou 0xc000010250
zouzou 0xc000010260
可以看到,我們把一個(gè)變量賦值給另一個(gè)變量后,內(nèi)存地址是不一樣的,因?yàn)闀?huì)新開辟一塊內(nèi)存地址。不像 python 語言,會(huì)指向同一塊內(nèi)存地址
例子
package main
import "fmt"
func main() {
name := "zouzou"
nickName := name
fmt.Println(name, &name)
fmt.Println(nickName, &nickName)
name = "daliu" // 修改了name 的值,但是內(nèi)存地址還是之前的,只是在之前的內(nèi)存地址上修改了值
fmt.Println(name, &name)
fmt.Println(nickName, &nickName) // 值類型,會(huì)拷貝一份
}
結(jié)果
zouzou 0xc000010250
zouzou 0xc000010260
daliu 0xc000010250
zouzou 0xc000010260
可以看到,當(dāng)我們改變變量的值后,內(nèi)存地址沒有變,只是改變了內(nèi)存地址里對(duì)應(yīng)的數(shù)據(jù)。而賦值后的變量 nickName 是不會(huì)變的,因?yàn)槭切麻_辟的內(nèi)存地址,沒有改變這個(gè)內(nèi)存地址的值
注意:使用 int、string、bool、數(shù)組 這幾種數(shù)據(jù)類型時(shí),如果遇到變量的賦值則會(huì)拷貝一份。【值類型】

浙公網(wǎng)安備 33010602011771號(hào)