Effective Go 读书笔记

206 阅读3分钟

Functions

返回多个值

命名的结果参数

Defer

defer有点像final,预定了一个函数一定被调用(Call),在本方法return后。

Defer像Close这样的函数有两个好处,其一,这样保证不会忘记关闭文件,一种可能的情况是,你在函数中间新加了一个return路径,就导致close漏了。其二是,把Close放在离Open比较近的地方, 这样比把Close放在函数的最后更加清晰。

传入Defer的函数的参数,是在defer执行时就计算好的, 而不是在调用时再计算的。

多个defer的函数进入 FILO 的队列。

Data

使用new分配内存

but unlike its namesakes in some other languages it does not initialize the memory, it only zeros it.

Go不会在new的同时初始化一些值,而是会将内存置零。也就是所有对象,申请出来,都是零值,如果需要值,后面再去设置。

new(T) 分配出来的是 zero value of T。

构造器

有时候零值结构体不行, 就需要一个构造器,GO的风格是写一个构造函数,如下例子,这个os包的例子

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }
    f := new(File)
    f.fd = fd
    f.name = name
    f.dirinfo = nil
    f.nepipe = 0
    return f
}

composite literals

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }
    f := File{fd, name, nil, 0}
    return &f
}

Note that, unlike in C, it's perfectly OK to return the address of a local variable; the storage associated with the variable survives after the function returns. In fact, taking the address of a composite literal allocates a fresh instance each time it is evaluated, so we can combine these last two lines.

返回本地变量的地址也是OK的,该存储在函数返回之后,依旧会生存,不会消失。

    return &File{fd, name, nil, 0}

上面的File字面值没有字段名,这时,字段必须要全。 如果只想要指定部分的字段,其余保留零值,那么可以加上字段名,如下所示。

The fields of a composite literal are laid out in order and must all be present. However, by labeling the elements explicitly as field:value pairs, the initializers can appear in any order, with the missing ones left as their respective zero values. Thus we could say

    return &File{fd: fd, name: name}

极限情况,一个值也没有,那么就等同于new了。

The expressions new(File) and &File{} are equivalent.

a := [...]string   {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
s := []string      {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}

在上面这个例子中, Enone,Eio,Einval都是int值。对于前两个,没有指定的index,就是零值。自己试一下能理解。

Allocation with make

make只用来创建 slice,maps,channel,返回初始化的 类型T,而不是指针。 slice是一个具有三项内容的描述符,一个指向数据的指针,一个长度以及容量。

arrays

数组是值,把一个数组赋值给另一个数组,会拷贝所有的元素。

特别地,若将某个数组传入某个函数,它将接收到该数组的一份副本而非指针。

初始化Initialization

常量

常量在编译时创建。