为什么没有为命名指针类型定义方法?

时间:2015-07-19 22:31:42

标签: go

effective Go的文档中,它声明:

  

正如我们在ByteSize中看到的那样,可以为任何命名类型定义方法   (指针除外......

type ByteSlice []byte
func (slice ByteSlice) Append(data []byte) []byte {
  // Body exactly the same as above
}

然后继续提供一个指针作为接收器的例子:

func (p *ByteSlice) Append(data []byte) {
  slice := *p
  // Body as above, without the return.
  *p = slice
}

这不矛盾吗?或者这是否意味着这是无效的:

type ByteSlice []byte
type Pb *ByteSlice
func (p Pb) Append(data []byte) []byte {
} 

虽然它看起来就像一个typedef!

2 个答案:

答案 0 :(得分:2)

命名指针类型可能会导致模糊不清:

type T int 

func (t *T) Get() T { 
    return *t + 1 
} 

type P *T 

func (p P) Get() T { 
    return *p + 2 
} 

func F() { 
    var v1 T 
    var v2 = &v1 
    var v3 P = &v1 
    fmt.Println(v1.Get(), v2.Get(), v3.Get()) 
}

在最后一种情况下(特别是v3),根据当前规范,应该调用Get()方法是不明确的。是的,没有理由不能定义方法解决方案,但是为已经有解决方案的东西添加到语言中还有一个细节。

答案 1 :(得分:2)

作为指针的命名类型与指向命名类型的指针不同。

这是语言参考所说的:

  

该参数部分必须声明一个参数,即接收器。   其类型必须为T或* T形式(可能使用括号)   其中T是类型名称。由T表示的类型称为接收器   基础类型;它不能是指针或接口类型,它必须是   在与方法相同的包中声明。

这很清楚:如果T表示指针类型,那么你不能将它用作方法接收器。

请注意此处引用的谨慎语言:短语“其类型必须为T或T *形式”是指方法接收器的语法级规范(即该类型的“形式”) 。这与短语“由T表示的类型”不同,它在谈论T名称的类型(即,类型“表示”)。