函数

在go的世界中,函数是一等公民,可以给变量赋值,可以作为参数传递,也可以直接赋值。

多值返回

https://golang.org/doc/effective_go.html#multiple-returns

Go的一个不同寻常的特点是,函数和方法可以返回多个值。这种形式可以用来改进C程序中的几个笨拙的习语:带内错误返回,如-1代表EOF和修改按地址传递的参数。

在C语言中,写错误的信号是一个负数,错误代码被秘密存放在一个易失性的位置。在Go中,Write可以返回计数(count)和错误(error)。”是的,你写了一些字节,但不是全部,因为你填满了设备”. 来自包os的文件上的Write方法的签名是。

func (file *File) Write(b []byte) (n int, err error)

和文档中说的一样,当 n != len(b) 时,它返回写入的字节数和一个非nil错误。这是一种常见的风格;更多的例子请参见错误处理一节。

类似的方法避免了传递指针到返回值以模拟引用参数的需要。下面是一个简单的函数,用于从字节片中的某个位置抓取一个数字,返回数字和下一个位置。

func nextInt(b []byte, i int) (int, int) {
    for ; i < len(b) && !isDigit(b[i]); i++ {
    }
    x := 0
    for ; i < len(b) && isDigit(b[i]); i++ {
        x = x*10 + int(b[i]) - '0'
    }
    return x, i
}

你可以用它来扫描输入切片b中的数字,像这样。

    for i := 0; i < len(b); {
        x, i = nextInt(b, i)
        fmt.Println(x)
    }

命名结果参数

Go函数的返回或结果 “参数 “可以被赋予名称,并作为常规变量使用,就像传入参数一样。当命名时,它们在函数开始时被初始化为其类型的零值;如果函数执行一个没有参数的返回语句,结果参数的当前值被用作返回值。

这些名称并不是强制性的,但它们可以使代码更短、更清晰:它们是文档。如果我们给 nextInt 的结果命名,就会很明显地知道哪个返回的 int 是哪个。

func nextInt(b []byte, pos int) (value, nextPos int) {

因为被命名的结果是初始化的,并且与一个不加修饰的返回相联系,所以它们可以简化以及澄清。下面是一个很好地使用它们的 io.ReadFull 版本。

func ReadFull(r Reader, buf []byte) (n int, err error) {
    for len(buf) > 0 && err == nil {
        var nr int
        nr, err = r.Read(buf)
        n += nr
        buf = buf[nr:]
    }
    return
}

defer

详见 defer 语句。

函数的本质

摘录自 函数——go世界中的一等公民 “函数的本质” 一节

在go的世界中,函数是一等公民,可以给变量赋值,可以作为参数传递,也可以直接赋值。

函数在go语言里的本质其实就是指向 __TEXT 段内存地址的一个指。

参考资料