pointers - 接口(interface)的golang地址和接口(interface)区别

标签 pointers go interface pass-by-reference pass-by-value

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

(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 和 bytes.Buffer 都实现了 io.Writer 接口(interface),所以我认为它们应该具有相同的行为。

当我变成

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

jetbrains goland 告诉我

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

我想知道为什么 buf 有一个 '&' 可以工作,但另一个不工作?

我google了一下,有人说给函数传值的时候,可以引用&w

但是另一个说如果你传递一个指针,它可以遵从值

来自 https://github.com/golang/go/wiki/MethodSets#variables

To make it easier to remember these rules, it may be helpful to simply consider the pointer- and value-receiver methods separately from the method set. It is legal to call a pointer-valued method on anything that is already a pointer or whose address can be taken (as is the case in the above example). It is legal to call a value method on anything which is a value or whose value can be dereferenced (as is the case with any pointer; this case is specified explicitly in the spec).

我完全糊涂了,我自己也搞不懂。 希望您能帮帮我,谢谢!

最佳答案

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

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

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

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. 一个接口(interface)(通常)已经是一个指针。

你的例子

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

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

bytes.Buffer 类型的变量 b 是一个 struct,正如您从源代码中看到的那样:

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.Writer(接口(interface)),你需要获取 bytes.Buffer 的指针,因为(通常)在 go 中使用指针方法:fmt。 Fprintf(&b, "一些文本")

类型为 http.ResponseWriter 的变量 w 是一个 interface:

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

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

接口(interface)初始化

接口(interface)本身不能被初始化和使用!你总是需要一个结构或其他类型来实现接口(interface),然后你可以初始化它并将它用作类型 SomeInterface。 例如here is the implementation of gin对于 http.ResponseWriter。从代码中可以看出,它的方法使用指针接收器。所以 http.ResponseWriter 已经是一个指向结构的指针。

免责声明

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

关于pointers - 接口(interface)的golang地址和接口(interface)区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52061348/

相关文章:

networking - 在特定网络接口(interface) (JSch) 上打开 SSH 连接

c - GtkMenuItem - 侧面的空白区域

c - C语言中 "string"的通用交换

C++ 智能指针地址

c++ - 删除指针时出错

json - Reflect vs Regex 检查 Golang 中的空 JSON 数组属性

c - 在数组中查找元素时应用程序崩溃

运行时崩溃

go - 在 Go 中强制映射类型

java - 在java中将接口(interface)转换为上层类