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
常量
常量在编译时创建。