【发布时间】:2021-10-06 06:02:12
【问题描述】:
当客户端结构嵌入接口时,即使提供的结构没有“实现”接口,代码也能正常编译。
以下面 2 秒后发生恐慌并恢复的例子来说明问题:
service.go
package service
import (
"fmt"
)
type (
Service struct {
clients []Client
}
Client interface {
Valid() bool
Run()
}
)
func (s *Service) AddClient(client Client) {
defer func() {
if e := recover(); e != nil {
fmt.Println("recovered: ", e)
}
}()
// Question:
// Instead of panic here let client know that
// their CustomClient is missing Valid implementation
//
// fmt.Printf("%T does not implement Client (missing Valid method)\n", client)
// return
if !client.Valid() {
return
}
s.clients = append(s.clients, client)
}
// Run expects that
func (s *Service) Run() {
fmt.Println("Service Run")
if len(s.clients) > 0 {
for _, client := range s.clients {
client.Run()
fmt.Println("Client Run")
}
} else {
fmt.Println("Service Invalid")
}
}
example_invalidclient_test.go想让这个测试通过
package service_test
import (
"fmt"
"service"
"time"
)
type CustomClient struct {
service.Client
}
func (c *CustomClient) Run() {
fmt.Println("CustomClient run")
}
func ExampleInvalidClient() {
time.Sleep(2 * time.Second)
c := &service.Service{}
c.AddClient(&CustomClient{})
c.Run()
// Output:
// *service_test.CustomClient does not implement Client (missing Valid method)
// Service Run
// Service Invalid
}
go test .
--- FAIL: ExampleInvalidClient (2.00s)
got:
recovered: runtime error: invalid memory address or nil pointer dereference
Service Run
Service Invalid
want:
*service_test.CustomClient does not implement Client (missing Valid method)
Service Run
Service Invalid
是否可以在编译时检测到它,而不是进行自定义运行时验证并呈现编译错误,例如缺少实现错误。或者在恐慌恢复中获得更明确的恐慌原因而不是runtime error: invalid memory address or nil pointer dereference?
例如更清晰的错误就像示例测试
*CustomClient does not implement Client (missing Valid method)
比寻找包代码(*Service).AddClient(...)做什么
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x497b3c]
goroutine 1 [running]:
main.(*Service).AddClient(...)
【问题讨论】:
-
CustomClient实现了Client接口。它嵌入了它。 -
@BurakSerdar 在这种情况下实施可能是错误的定义。
client.Valid == nil是错误的,但client.Valid()会出现恐慌,所以我的意思是不实施 -
client.Client为零,因为您从未初始化它。client.Valid永远不能为零,它是一个函数。
标签: go