为什么Go语言允许指向接口的指针?

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

Why does Go allow pointers to interfaces?

问题

在我写Go代码的任期中,我从未遇到过一种情况,也无法想到一种情况,需要使用指向接口的指针,除非是编写一个大量使用运行时反射的库。一些人提到了有合理的理由这样做,但似乎从未详细说明。这个特性似乎也给那些刚开始使用Go的开发者带来了很多困惑。

main.go:22: 无法将&a (类型 *A) 作为类型 **interface {} 的参数传递给 run

有没有一个使用接口指针的好例子?

英文:

In my tenure of writing Go code, I have never encountered a case, nor can I think of one that would require using a pointer to an interface, except for perhaps writing a library that makes heavy use of runtime reflection. Some people allude to the fact that there are valid reasons for doing so, but seem to never elaborate further. This feature also seems to cause quite a bit of confusion with developers who are getting started with Go.

main.go:22: cannot use &a (type *A) as type **interface {} in argument to run

What would be a good example of using an interface pointer?

答案1

得分: 4

在语言规范中,有一个特殊情况需要禁止指向接口的指针。这使得语言更加复杂。

创建一个接口类型的reflect.Type是一个场景,其中指向接口的指针非常有用:reflect.TypeOf((*io.Closer)(nil)).Elem()io.Closer的反射类型。

英文:

A special case in the language specification is required to disallow pointers to interfaces. That makes the language more complex.

Creating a reflect.Type for an interface interface type is one scenario where pointers to interfaces come in handy: reflect.TypeOf((*io.Closer)(nil)).Elem() is the reflect type of io.Closer.

答案2

得分: 1

我可以给你提供一个例子,但是我从未在实际应用中使用过,也没有见过。这个例子是让另一个函数填充你的接口。

以下是示例代码:

package main

import "fmt"

func main() {
    var s fmt.Stringer
    setMyStringer(&s)
    fmt.Println("Hello, stringer:", s)
}

func setMyStringer(target *fmt.Stringer) {
    *target = Stringable(5)
}

type Stringable int

func (s Stringable) String() string {
    return fmt.Sprint(int(s))
}

你可以在这里查看示例运行结果。我很难想象出需要这样做的情况。正如其他人指出的,不允许这样做可能是错误的,因为这会使编译器变得更加复杂。

英文:

Only example I can come up with, but never used nor seen in the wild, is to let another function populate your interface.

Example on Play. I can't really imagine a case where it is needed.
As others have pointed out, not allowing it would probably be wrong as that would make the compiler more complicated.

package main

import "fmt"

func main() {
	var s fmt.Stringer
	setMyStringer(&s)
	fmt.Println("Hello, stringer:", s)
}

func setMyStringer(target *fmt.Stringer) {
	*target = Stringable(5)
}

type Stringable int

func (s Stringable) String() string {
	return fmt.Sprint(int(s))
}

huangapple
  • 本文由 发表于 2016年4月5日 07:14:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/36414501.html
匿名

发表评论

匿名网友

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

确定