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
", 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
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
", conn)
return conn, nil
}
// now the dialer field can be set to *customDialer and net.Dialer as well
type dialerConsumer struct {
dialer Dialer
}