Go编程tips-1

结构体的初始化

示例代码中,前者是创建普通对象,后者是创建指针

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?

发表评论

电子邮件地址不会被公开。 必填项已用*标注