-2

我正在尝试一个与接口的结构嵌入相关的示例

// https://talks.golang.org/2014/go4java.slide#52
// Struct embedding of interfaces
// https://play.golang.org/p/SYiZ7M1OEhU

package main

import (
    "bytes"
    "fmt"
    "net"
)

// net.Conn has Read and Write

type loopBack struct {
    net.Conn
    buf bytes.Buffer
}

func (c *loopBack) Read(b []byte) (int, error) {
    fmt.Println("loopBack Read")
    return 0, nil 
}

func main() {

    loop := loopBack{}
    loop.Read(nil)
    loop.Write(nil)                                                                           
}

并且该Write方法未定义,因此我收到此运行时错误

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0xe28ca]

goroutine 1 [running]:
main.main()
    /tmp/sandbox812386031/main.go:28 +0x6a

存在某种在编译时验证它的方法吗?

链接到代码

https://play.golang.org/p/SYiZ7M1OEhU

4

2 回答 2

0

你在做什么和说“”是一样的loopBack implements net.Conn
要获取有关缺少的方法的编译时错误——以及不匹配的方法Read()——声明loop的类型:(
并且不要net.Conn嵌入loopBack

func main() {
  var loop net.Conn = loopBack{}

于 2019-01-28T17:26:07.690 回答
0

Golang不需要显式接口实现。你在这里做什么:

type loopBack struct {
    net.Conn
    buf bytes.Buffer
}

是否类似于:

type loopBack struct{
    Conn net.Conn
    buf bytes.Buffer
}

net.Conn作为接口类型,您的loopBack类型的第一个字段可以是实现该接口的任何内容,net.Conn这当然不仅仅是单独的(参见此处)。ReadWrite

嵌入类型的优点是字段和接收函数(名称冲突除外)可以直接在嵌入它们的类型上访问。

使用嵌入式net.Conn字段,您确实可以编写:

loop.Write(nil)

如果Conn字段已初始化(否则,其值为nil)。将声明更改为第二个版本,loop.Write将不起作用,您必须编写:

loop.Conn.Write(nil)

类型嵌入非常强大,但是当您第一次开始使用时,会有很多问题。谢天谢地,有一个完整的段落解释了有效的 go doc中的嵌入

无论如何,如前所述,您可以调用函数和访问字段(如果您嵌入的是结构类型而不是接口)。但是,有一件事:必须正确初始化该字段!

这就是您出错的地方:您仍然必须初始化变量的Conn一部分loopBack,否则您所做的与以下内容相同:

net.Conn(nil).Write(nil)

这自然会导致恐慌(无指针取消引用)......

例如:

conn, err := net.Dial("tcp", "localhost:80")
if err != nil {
    log.Fatalf("failed to dial localhost: %+v", err)
}
loop := loopBack{
    Conn: conn,
}
loop.Write(nil) // same as conn.Write(nil)

未能设置net.Conn嵌入字段类似于执行以下操作:

s := make([]*int, 10) // make slice of 10 pointers to int
fmt.Println(len(s)) // outputs 10
*s[0]++ // add 1 to first element PANICS

切片中的 10 个元素存在,但它们都已初始化为nil

于 2019-01-28T20:00:52.193 回答