Golang接口地址和接口区别

golang address of interface and interface difference

提问人:nuclear 提问时间:8/28/2018 更新时间:8/29/2018 访问量:2242

问:

我发现了很多类似的问题,但不是我想要的 请参阅以下代码。

(1)

var buf bytes.Buffer
fmt.Fprint(&buf,"test")

(2)

var w http.ResponseWriter
http.Error(w,http.StatusText(http.StatusBadRequest),http.StatusBadRequest)

两个 http.ResponseWriter 和字节。缓冲区实现 io。编写器界面,所以我认为它们应该具有相同的行为。

当我更改为

http.Error(&w,http.StatusText(http.StatusBadRequest),http.StatusBadRequest)

Jetbrains Goland告诉我

Cannot use '&w' (type *http.ResponseWriter) as type ResponseWriter

我想知道为什么“&”可以工作,而另一个不起作用?buf

我用谷歌搜索了一下,有人说当将值传递给函数时,它可以引用&w

但另一种说法是,如果你传递一个指针,它可以尊重价值

https://github.com/golang/go/wiki/MethodSets#variables 相比

为了便于记住这些规则,简单地将指针和值接收器方法与方法集分开考虑可能会有所帮助。对已经是指针或可以获取其地址的任何内容调用指针值方法是合法的(如上面示例中的情况)。对任何值或其值可以取消引用的事物调用值方法是合法的(就像任何指针一样;这种情况在规范中明确指定)。

我完全糊涂了,我自己也听不懂。 我希望你能帮助我,谢谢!

指针 GO 接口 按引用传递 值传递

评论

2赞 Adrian 8/28/2018
bytes.Buffer是具体类型,是接口类型。关于方法的指针/值接收器的注释是无关的。http.ResponseWriter
0赞 Adrian 8/28/2018
该函数具体来说,接受 a ,但您传递的是 a(正如错误所说)。函数参数(不是方法接收器)的类型错误。http.Errorhttp.ResponseWriter*http.ResponseWriter
0赞 Himanshu 8/28/2018
如果您看到定义,则不需要指向它的指针。这是错误背后的原因,而不是您正在考虑的原因。func Error(w ResponseWriter, error string, code int)ResponseWriter
1赞 Volker 8/28/2018
你真的应该深入研究 Go 的类型系统。它不是神奇地或随机地把 & 和 * 放在东西之前。您必须了解不同的类型,例如结构类型(字节。Buffer)和接口类型(http.ResponseWriter)并了解方法集。SO 不是获得此答案的正确位置。你可以试试reddit或golang-nuts。
1赞 Jonathan Hall 8/28/2018
两者都是 s,是的,但都不是 s。io.Writerhttp.ResponseWriter

答:

1赞 TehSphinX 8/29/2018 #1

也许我可以尝试更详细地解释所有非常好的评论已经在说什么:

接口(大部分)是 go 中的指针

如果另一个类型实现了接口定义的所有方法,则 go 中的接口被实现(满足)。通常,这是通过在类型的指针上添加方法完成的,而不是直接在类型上添加方法。

type SomeInterface interface {
    SomeMethod string
}

type SomeStruct struct {} // often is a struct but does not have to be

// a method on the structs pointer
func (s *SomeStruct) SomeMethod string {
    return ""
}

其结果:

  1. SomeStruct不实现 SomeInterface,确实如此!*SomeStruct
  2. 接口(通常)已经是一个指针。

你的例子

var b bytes.Buffer
fmt.Fprintf(&b, "some text")

var w http.ResponseWriter
http.Error(w, "some error", 1)

从源代码中可以看出,类型的变量是:bbytes.Bufferstruct

type Buffer struct {
    buf       []byte   // contents are the bytes buf[off : len(buf)]
    off       int      // read at &buf[off], write at &buf[len(buf)]
    bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
    lastRead  readOp   // last read operation, so that Unread* can work correctly.

    // FIXME: it would be advisable to align Buffer to cachelines to avoid false
    // sharing.
}

如果要将其用作 io 类型。编写器(接口)你需要得到一个指针,因为(通常)指针方法在go中使用:bytes.Bufferfmt.Fprintf(&b, "some text")

http 类型的变量。ResponseWriter 是一个:winterface

type ResponseWriter interface {
    Header() Header
    Write([]byte) (int, error)
    WriteHeader(statusCode int)
}

由于接口(通常)已经是指向某些底层实现的指针,因此我们可以在不使用指针的情况下使用它:。http.Error(w, "some error", 1)

接口初始化

接口本身无法初始化和使用!你总是需要一个结构或其他类型来实现接口,然后你可以初始化它并将其用作类型。 例如,这里是 gin for a 的实现。从代码中可以看出,它使用指针接收器作为其方法。所以 http.ResponseWriter 已经是指向结构的指针。SomeInterfacehttp.ResponseWriter

免責聲明

这只是试图让这个复杂的话题听起来简单的一种方式(希望如此)。这在技术上不是一个完整或完全准确的解释。尽量保持简单,但尽可能准确。