5.10. 方法
5.10.1. 指针vs值
方法可用于任意带名的非指针和界面的类型;接受者没必要是结构。
在上面讨论切片时,我们写了个 Append 函数。其实我们可以把它定义为切片的方法。首先我们声明一个带名的类型,以便我们在其上施加方法,并使此方法的接受者的值是此类型。
type ByteSlice []byte
func (slice ByteSlice) Append(data []byte) []byte {
// Body exactly the same as above
}
这仍需方法返回更新的切片,更灵活的方式是定义方法接受 ByteSlice 的指针,以便重写调用着的切片。
func (p *ByteSlice) Append(data []byte) {
slice := *p
// Body as above, without the return.
*p = slice
}
实际上,我们能做的更好。如果我们把函数改的像标准的 Write 方法,例如:
func (p *ByteSlice) Write(data []byte) (n int, err os.Error) {
slice := *p
// Again as above.
*p = slice
return len(data), nil
}
此时类型 *ByteSlice 可以满足标准界面 io.Writer,很方便的,例如我们打印到里面:
var b ByteSlice
fmt.Fprintf(&b, "This hour has %d days\n", 7)
我们传递 ByteSlice 的地址是因为只有 *ByteSlice 满足 io.Writer。接受者的指针和值规则是,值的方法可用于指针和值,而指针的方法只用于指针。这是因为指针方法可以改变接受者;使用拷贝的值会导致这些改变的丢失。
顺便一提,字节切片的 Write 已在 bytes.Buffer 实现。