我正在尝试一个与接口的结构嵌入有关的示例
// 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
在编译时是否存在某种验证方法?
链接到代码答案 0 :(得分:0)
您正在做的是 而不是说“ NaN
”。
要获取有关缺少的方法以及不匹配的loopBack implements net.Conn
的编译时错误,请声明Read()
的类型:
(并且不要将net.Conn
嵌入loop
中)
loopBack
答案 1 :(得分:0)
Golang不需要 exlicit 接口实现。您在这里做什么:
type loopBack struct {
net.Conn
buf bytes.Buffer
}
类似于:
type loopBack struct{
Conn net.Conn
buf bytes.Buffer
}
net.Conn
是一种接口类型,您的loopBack
类型的第一个字段可以是实现net.Conn
接口的任何内容,当然它要比Read
和{ {1}}(see here)。
嵌入类型的优点在于,可以直接在嵌入它们的类型上访问字段和接收器函数(不包括名称冲突)。
有了嵌入式Write
字段,您确实可以编写:
net.Conn
如果,loop.Write(nil)
字段已初始化(否则,其值为Conn
)。将声明更改为第二个版本nil
无效,您必须编写:
loop.Write
类型嵌入功能非常强大,但是当您第一次入门时,会有很多陷阱。幸运的是,有一整段说明了嵌入effective go doc
无论如何,如上所述,您可以调用函数并访问字段(如果要嵌入结构类型而不是接口)。但是,有一件事:必须正确初始化字段!
这就是您出问题的地方:您仍然必须初始化 loop.Conn.Write(nil)
变量的Conn
部分,否则您所做的与以下操作相同:< / p>
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
切片中存在10个元素,但它们都已初始化为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