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

huangapple go评论82阅读模式
英文:

Why no methods defined for named pointer types?

问题

在《effective Go》文档中提到:

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

type ByteSlice []byte
func (slice ByteSlice) Append(data []byte) []byte {
  // 与上面完全相同的代码
}

然后它继续提供了一个以指针作为接收器的示例:

func (p *ByteSlice) Append(data []byte) {
  slice := *p
  // 与上面相同的代码,但没有返回值。
  *p = slice
}

这是否与之前的说法相矛盾?或者这是否意味着以下代码无效:

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

尽管它看起来只是一个类型定义!

英文:

In the documentation for effective Go it states:

> As we saw with ByteSize, methods can be defined for any named type
> (except a pointer ...

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

It then goes on to provide an example with a pointer as receiver:

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

Doesn't that contradict ? Or does it mean that this isn't valid:

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

Though it looks just like a typedef!

答案1

得分: 5

命名指针类型可能会导致歧义,例如:

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()方法。是的,方法解析可以被定义,但这只是为了解决已经有解决方案的问题而增加了一个细节。

英文:

Named pointer types could lead to ambiguities like so:

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()) 
}

In the last case (esp. v3) per the current spec, it's ambiguous which Get() method should be called. Yes, there's no reason that the method resolution couldn't be defined, but it's one more detail to add to the language for something that already has a solution.

答案2

得分: 3

一个被命名的类型,它是一个指针,并不等同于一个指向被命名类型的指针。

这是语言参考中的说明:

参数部分必须声明一个单一的参数,即接收器。
它的类型必须是形如 T 或 *T(可能使用括号)的形式,
其中 T 是一个类型名。T 所表示的类型被称为接收器的基本类型;
它不能是指针类型或接口类型,并且必须在同一个包中声明。

这已经很清楚了:如果 T 表示一个指针类型,那么你不能将其用作方法的接收器。

请注意参考文档中的谨慎措辞:短语“它的类型必须是形如 T 或 T*”是指方法接收器的语法级别规范(即类型的“形式”)。这与短语“T 所表示的类型”不同,后者是指 T 所代表的类型(即类型的“表示”)。

英文:

A named type that is a pointer isn't the same as a pointer to a named type.

This is what the language reference says:

> That parameter section must declare a single parameter, the receiver.
> Its type must be of the form T or *T (possibly using parentheses)
> where T is a type name. The type denoted by T is called the receiver
> base type; it must not be a pointer or interface type and it must be
> declared in the same package as the method.

That's clear enough: if T denotes a pointer type, then you can't use it as a method receiver.

Note the careful language of the reference here: the phrase "Its type must be of the form T or T*" refers to the syntax-level specification of the method receiver (that is, the "form" of the type). That's different from the phrase "The type denoted by T", where it's talking about the type that T names (that is, what the type "denotes").

huangapple
  • 本文由 发表于 2015年7月20日 06:31:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/31506625.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定