接口的golang地址和接口的区别

时间:2018-08-28 15:19:12

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

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

(1)

add_executable(foo src/foo1.cpp)
add_executable(bar src/bar2.cpp)
add_executable(baz src/baz3.cpp)

set(SPECIAL_TRGTS foo bar baz)

foreach(trgt ${SPECIAL_TRGTS})
  add_dependencies(${trgt} some_dependency)
  target_link_libraries(${trgt} mylib)
endforeach()

# and/or

set_target_properties(${SPECIAL_TRGTS} PROPERTIES
  PROP1 val1
  PROP2 val2)

(2)

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

http.ResponseWriter和bytes.Buffer都实现了io.Writer接口,所以我认为它们应该具有相同的行为。

当我更改为

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

jetbrains goland告诉我

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

我想知道为什么Cannot use '&w' (type *http.ResponseWriter) as type ResponseWriter 的'&'可以工作,而另一个不工作?

我用google搜索,有人说将值传递给函数时,它可以引用buf

但是又说一句,如果您传递一个指针,它可以引用值

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

  

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

我很困惑,我自己听不懂。 希望您能帮助我,谢谢!

1 个答案:

答案 0 :(得分:0)

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

接口(通常是go中的指针)

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

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)

类型b的变量bytes.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.Writer(接口)类型,则需要获取bytes.Buffer的指针,因为(通常)在go中使用了指针方法:fmt.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)

接口初始化

接口本身无法初始化和使用!您始终需要一个结构或其他类型来实现该接口,然后可以对其进行初始化并将其用作类型SomeInterface。 例如,here is the implementation of gin代表http.ResponseWriter。从代码中可以看到,它使用指针接收器作为其方法。因此http.ResponseWriter已经是一个指向结构的指针。

免责声明

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