1 - 声明
go语言中有四个主要声明:变量( var ) - 常量( const ) - 类型( type )- 函数( func )
例:下面的程序声明一个常量 / 一个函数 和 一对变量
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)
}
下面函数 fToC 封装量温度转换的逻辑,这样可以只定义一次而在多个地方使用。这里main调用了他两次。
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 - 指针
如果一个变量声明为var x int ,表达式 &x ( x 的地址 ) 获取一个指向整型的指针
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
}
# 每次调用 f() 都会返回一个不同的值
func main() {
fmt.Println(f() == f()) # false
}
# =============================================
# 因为一个指针包含变量地址。所以传递一个指针参数给函数,能够让函数更新间接传递变量值
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函数()
内置函数new() 表达式new(T)创建一个未命名的T类型变量。初始化为T类型的零值,并返回其地址。
p := new(int)
fmt.Println(*p) # 0
*p = 2
fmt.Println(*p) # 2
4 - 变量的声明周期
声明周期是指在程序执行过程中变量存在的时间段。
# 变量 t 在循环开始时创建,x/y 在循环的每次迭代中创建。
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 函数里的x一定要使用堆空间,因为它在f函数返回后还可以从global变量访问,这种情况我们说x从f中逃逸。
# 相反,当g函数返回时,变量*y变得不可访问,可回收。因为*y不用逃逸。
# 不用逃逸在性能优化上是有好处的。因为每一次逃逸都需要额外的一次内存分配过程
var global *int
func f() {
var x int
x = 1
global = &x
}
func g() {
y := new(int)
*y = 1
}
网友评论