英文:
Extend struct in Go
问题
假设对象A具有类型为net.Dialer
的字段。我想为对象A提供一个自定义的net.Dialer
实现,以增强Dial
方法。在Go语言中是否可行?我尝试使用嵌入字段,代码如下:
package main
import (
"net"
"fmt"
)
type dialerConsumer struct {
dialer net.Dialer
}
func (dc *dialerConsumer) use() error {
conn, e := dc.dialer.Dial("tcp", "golang.org:http")
if e != nil {
return e
}
fmt.Printf("conn: %s\n", conn)
return nil
}
type customDialer struct {
net.Dialer
}
func main() {
standardDialer := net.Dialer{}
consumer := &dialerConsumer{
dialer: standardDialer,
}
consumer.use()
/*
customDialer := customDialer{
net.Dialer{},
}
consumer = &dialerConsumer{
dialer: customDialer,
}
consumer.use()
*/
}
然而,当我取消main
函数中被注释掉的代码时,我会得到以下编译错误:
src/test.go:38: cannot use customDialer (type customDialer) as type net.Dialer in field value
英文:
Suppose object A has a field of type net.Dialer
. I'd like to provide object A with a custom implementation of net.Dialer
that augments the Dial
method. Is this doable in Go? I'm trying to use embedded fields like so:
package main
import (
"net"
"fmt"
)
type dialerConsumer struct {
dialer net.Dialer
}
func (dc *dialerConsumer) use() error {
conn, e := dc.dialer.Dial("tcp", "golang.org:http")
if e != nil {
return e
}
fmt.Printf("conn: %s\n", conn)
return nil
}
type customDialer struct {
net.Dialer
}
func main() {
standardDialer := net.Dialer{}
consumer := &dialerConsumer{
dialer: standardDialer,
}
consumer.use()
/*
customDialer := customDialer{
net.Dialer{},
}
consumer = &dialerConsumer{
dialer: customDialer,
}
consumer.use()
*/
}
However, when I uncomment the commented-out code in main
, I get the following compilation error:
src/test.go:38: cannot use customDialer (type customDialer) as type net.Dialer in field value
答案1
得分: 6
你之所以出现错误,是因为customDialer
和net.Dialer
是两种不同的类型,不能互相替换使用。在Go语言中,嵌入不同于其他面向对象语言中的类继承,所以它不能帮助你实现你想要的功能。
在这种情况下,你可以使用Go语言的接口来实现类似多态/鸭子类型的功能。由于Go语言中的接口是隐式满足的,你可以定义一个新的接口,只要现有类型具有与新定义接口相同签名的方法,它就会自动实现该接口。
// 已经由net.Dialer实现
type Dialer interface {
Dial(network, address string) (net.Conn, error)
}
type customDialer struct {
*net.Dialer
}
func (cd *customDialer) Dial(network, address string) (net.Conn, error) {
conn, err := cd.Dialer.Dial(network, address)
if err != nil {
return nil, err
}
fmt.Printf("conn: %s\n", conn)
return conn, nil
}
// 现在dialer字段可以设置为*customDialer和net.Dialer
type dialerConsumer struct {
dialer Dialer
}
链接:https://play.golang.org/p/i3Vpsh3wii
英文:
You're getting the error because customDialer
and net.Dialer
are two different types and cannot be used interchangeably. Embedding in Go is not the same as class inheritance in other OO langauges so it won't help you with what you trying to do.
What you can do instead in this case is to use Go interfaces which give you something like polymorphism/duck-typing, and since interfaces in Go are satified implicitly you can define a new interface that an existing type will implement by virtue of having a method with the same signature as the newly defined interface.
// already implemented by net.Dialer
type Dialer interface {
Dial(network, address string) (net.Conn, error)
}
type customDialer struct {
*net.Dialer
}
func (cd *customDialer) Dial(network, address string) (net.Conn, error) {
conn, err := cd.Dialer.Dial(network, address)
if err != nil {
return nil, err
}
fmt.Printf("conn: %s\n", conn)
return conn, nil
}
// now the dialer field can be set to *customDialer and net.Dialer as well
type dialerConsumer struct {
dialer Dialer
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论