在Go中扩展结构

时间:2017-03-27 10:43:55

标签: go

假设对象A的字段为net.Dialer。我想为对象A提供net.Dialer的自定义实现,以增强Dial方法。这在Go中可行吗?我正在尝试使用embedded fields

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

1 个答案:

答案 0 :(得分:2)

您收到错误是因为customDialernet.Dialer是两种不同类型,因此无法互换使用。嵌入Go与其他OO语言中的类继承不同,因此它无法帮助您完成您想要做的事情。

在这种情况下你可以做的是使用Go接口,它给你类似多态/鸭子类型的东西,并且由于Go中的接口是隐含的,你可以定义一个现有类型将通过它实现的新接口使用与新定义的接口具有相同签名的方法。

// 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
}

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