教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Golang 接口 & 指针

Golang 接口 & 指针

发布时间:2022-02-26   编辑:jiaochengji.com
教程集为您提供Golang 接口 & 指针等资源,欢迎您收藏本站,我们将为您提供最新的Golang 接口 & 指针资源
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"/></svg>

如 http.Handler 接口,有个困惑,为什么 第一个参数是value类型,第二个参数是指针类型呢?

<pre><code>type Handler interface { ServeHTTP(ResponseWriter, *Request) } </code></pre>

Go里一切传递,都是传值,即便是指针。其实指针是一种特殊的类型包含了地址的值。

更进一步的发现,ResponseWriter 是接口类型。

<pre><code>type ResponseWriter interface { Header() Header Write([]byte) (int, error) WriteHeader(int) } </code></pre>

interface 在运行时,会保存一个实现接口的对象,结构体里有两行,一个指向类型,另一个指向它关联的数据。

如果没有任何的数据绑定在接口上,Go可以指示接口实现,并提供编译时候的类型检查。

<pre><code>//(1) The interface type Mutable interface { mutate(newValue string) error } //(2) Struct type Data struct { name string } //(3) Implements the interface with a pointer receiver func (d *Data) mutate(newValue string) error { d.name = newValue return nil } //(4) Function that accepts the interface func mutator(mute Mutable) error { return mute.mutate("mutate") } func main() { d := Data{name: "fresh"} fmt.Println(d.name) //fresh //(5) pass as a pointer mutator(&d) fmt.Println(d.name) //mutate } </code></pre>

在第三步,Data 实现了指针,可以改变内部的值

在第四步,函数 mutator 接受一个参数,来执行真正的改变操作。注意这里的参数是一个值,而不是指针。

第五步,我们传递了一个指针进去。貌似它违反了通常的golang 类型检查 type-check。例如,传递正常的类型会失败,但是传递接口是可以成功的。

例如下面的,就会编译失败

<pre><code>func thisWontWork(s string) { ... } v := "kirk" thisWontWork(&v) //compilation error </code></pre>

参数的类型检查,确保参数 interface 和 结构体的 receiver 一致。

<pre><code> --------------------------------------------- | method receiver | parameter | | ------------------------------------------| | pointer | pointer | |-------------------------------------------| | value | value | | | pointer (dereferenced) | --------------------------------------------- </code></pre>

让测一下上述的假设,通过改变 receiver 为一个 值类型,并传参为值。

<pre><code>//(1) Implements the interface with a value receiver func (d Data) mutate(newValue string) error { ... //(2) mutator function is UNCHANGED func mutator(mute Mutable) error { //(3) pass as value mutator(d) fmt.Println(d.name) //fresh </code></pre>

你仍然可以看到,这个结构体,同样符合 mutator 函数的要求。但是该函数可能不太符合我们要求了,因为原始的值没有改变。

以下会编译错误:

<pre><code>//(1) Implements the interface with a pointer receiver func (d *Data) mutate(newValue string) error { //(2) Function is UNCHANGED func mutator(mute Mutable) error { //(3) Pass as value. Results in compilation error. mutator(d) </code></pre>

interface 的实现者,可以有不同的类型的receivers

<pre><code>//(1) Define another struct that implements the interface type AnotherData struct {...} //(2) Implements as a value receiver. func (ad AnotherData) mutate(newValue string) error {...} //(3) Function is UNCHANGED func mutator(mute Mutable) error {...} //(4) Pass as a value. anotherData := AnotherData{name: "afresh"} fmt.Println(anotherData.name) //afresh mutator(anotherData) fmt.Println(anotherData.name) //afresh </code></pre>

回到最初我们讨论的 Handler, 这里的response 结构体实现了 ResponseWriter 接口,同样带着 指针类型的receivers
【这里要解释 receiver和函数的区别】
Http Server 生成了一个 返回结构体,然后作为一个指针传递给handlers,这样可以使得 handlers 写值进入response 对象。

<pre><code>//server.go - showing relevant code package http type response struct { ... //methods of ResponseWriter implemented by response func (w *response) Header() Header {... func (w *response) WriteHeader(code int) {... //readRequest returns a pointer to the response func ... readRequest(..) (w *response, err error) { return &response{...} } //serves the request func (c *conn) serve(ctx context.Context) { w_ptr, _ = readRequest(...) ... handler.ServeHTTP(w_ptr) </code></pre>

所以通常看来,即便 interface 可以被传值,更多的时候,它被作为指针来传递。

总结:

<ol><li>接口的实现方式决定了要传递的参数类型</li><li>值和指针receivers都是允许的,相同的接口,可以有不同的实现。</li><li>有人说 receivers 应该总是指针类型的,我会反驳,语言应该提供一个强制机制。</li></ol> 到此这篇关于“Golang 接口 & 指针”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
Go结构体继承指针和非指针区别(转换接口)
Golang-对象方法和实现接口时,方法接受者是指针还是对象的区别
golang传递接口类型参数时,什么时候用指针
GO接口赋值与方法接收者问题
Golang 接口 & 指针
golang 接口 参数
GoLang学习笔记(三十四)接口及空接口
go语言接口断言的使用
golang积累-接口指针与结构体指针
Go学习笔记:接口实现与指针

[关闭]
~ ~