1 - 聲明
go語言中有四個(gè)主要聲明:變量( var ) - 常量( const ) - 類型( type )- 函數(shù)( func )
例:下面的程序聲明一個(gè)常量 / 一個(gè)函數(shù) 和 一對變量
package main
import "fmt"
const boilingF = 212.0
func main() {
var f = boilingF
var c = (f - 32) * 5 / 9
fmt.Printf("boiling point = %gF or %gC\n", f, c)
}
下面函數(shù) fToC 封裝量溫度轉(zhuǎn)換的邏輯,這樣可以只定義一次而在多個(gè)地方使用。這里main調(diào)用了他兩次。
package main
import "fmt"
func main() {
const free, boil = 32.0, 212.0
fmt.Printf("%gF = %gC\n", free, fToC(free))
fmt.Printf("%gF = %gC\n", free, fToC(boil))
}
func fToC(f float64) float64 {
return (f - 32) * 5 / 9
}
2 - 指針
如果一個(gè)變量聲明為var x int ,表達(dá)式 &x ( x 的地址 ) 獲取一個(gè)指向整型的指針
x := 1
p := &x # p是整型指針,指向x
*p = 2 # 等于 x = 2
var x, y int
fmt.Println(&x == &x, &x == &y, &x == nil) # true false false
# =============================================
package main
import "fmt"
func f() *int {
v := 1
return &v
}
# 每次調(diào)用 f() 都會返回一個(gè)不同的值
func main() {
fmt.Println(f() == f()) # false
}
# =============================================
# 因?yàn)橐粋€(gè)指針包含變量地址。所以傳遞一個(gè)指針參數(shù)給函數(shù),能夠讓函數(shù)更新間接傳遞變量值
package main
import "fmt"
func incr(p *int) int {
*p++
return *p
}
func main() {
v := 1
incr(&v) # 副作用:v= 2
println(incr(&v)) # "3" v = "3"
}
3 - new函數(shù)()
內(nèi)置函數(shù)new() 表達(dá)式new(T)創(chuàng)建一個(gè)未命名的T類型變量。初始化為T類型的零值,并返回其地址。
p := new(int)
fmt.Println(*p) # 0
*p = 2
fmt.Println(*p) # 2
4 - 變量的聲明周期
聲明周期是指在程序執(zhí)行過程中變量存在的時(shí)間段。
# 變量 t 在循環(huán)開始時(shí)創(chuàng)建,x/y 在循環(huán)的每次迭代中創(chuàng)建。
for t := 0.0; t < cycles*2*math.Pi; t += res{
x := math.Sin(t)
y := math.Sin(t*freq + phase)
img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5),
blackIndex)
}
# 我們在 f 函數(shù)里的x一定要使用堆空間,因?yàn)樗趂函數(shù)返回后還可以從global變量訪問,這種情況我們說x從f中逃逸。
# 相反,當(dāng)g函數(shù)返回時(shí),變量*y變得不可訪問,可回收。因?yàn)?y不用逃逸。
# 不用逃逸在性能優(yōu)化上是有好處的。因?yàn)槊恳淮翁右荻夹枰~外的一次內(nèi)存分配過程
var global *int
func f() {
var x int
x = 1
global = &x
}
func g() {
y := new(int)
*y = 1
}