结构体的初始化
示例代码中,前者是创建普通对象,后者是创建指针
package main
import (
"fmt"
)
type Rect struct {
x, y float64
width, height float64
}
func main() {
// common object
rect2 := Rect{}
rect3 := Rect{0, 0, 100, 200}
rect4 := Rect{width: 100, height: 200}
fmt.Println(rect2, rect3, rect4)
/*
// pointer objects
rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{0, 0, 100, 200}
rect4 := &Rect{width: 100, height: 200}
fmt.Println(rect1, rect2, rect3, rect4)
*/
}
变参
go支持变参,变参中所有参数的类别必须是同一种,且必须是最后一个形参。使用方法如下:“…type”表示具有不定个type类型的参数,不定参数实质上是一个slice类型,故可以使用range对其参数进行取值。如下例子。
func myfunc(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
}
defer 与return执行顺序
当函数执行到最后时,先执行defer语句,然后才执行return语句.所以可以利用这个来进行资源安全关闭,解加锁,记录执行情况等。defer是采用先进后出的模式的,这种情形与栈的情况一致。注意:定义的defer延迟操作,如有提供参数会发生值的拷贝,尽管这些函数在退出时才执行,但所使用的参数是在定义时就进行拷贝,拷贝的原则和变量的赋值原则一个,slice,map,channel是指针拷贝.如下例子:
package main
import (
"fmt"
)
func main() {
x := 1
defer func(a int) { //直接将x=1赋值给a,虽然他在后面才执行.
fmt.Println("a=", a)
}(x)
defer func() {
fmt.Println("x=", x) //经过x++后,x值变为2
}()
x++
}
运行结果:
x= 2
a= 1
临时变量的作用域
go语言中对于堆和栈的内存分配没有严格区分,在go中返回一个局部变量的地址是绝对没有问题的,变量关联的存储在函数返回后依然存在.(注:尤其对由C/C++转过来的程序员,开始肯定不是很适应,但是go这种内存分配方式解放了程序员,使得程序员能够专注做事情,而不用花费太多的时间在堆和栈的内存分配上).更直接的说,在go语言中,如果一个局部变量在函数返回后仍然被使用,那么这个变量会在堆heap,而不是栈stack中进行内存分配.详情参考How do I know whether a variable is allocated on the heap or the stack?