在 Go 中扩展结构

Pau*_*l I 3 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()
    */
}
Run Code Online (Sandbox Code Playgroud)

但是,当我取消注释中注释掉的代码时main,出现以下编译错误:

src/test.go:38: cannot use customDialer (type customDialer) as type net.Dialer in field value
Run Code Online (Sandbox Code Playgroud)

mko*_*iva 5

您收到错误是因为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
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果你无法控制 `A`,那么你是对的,你不能将 `Dialer` 接口分配给它,并且你不能在 Go 中将除 `net.Dialer` 之外的任何其他东西分配给 `net.Dialer` 类型的字段`...接下来最好的事情是包装对象`A`并在调用`Dial`之前做任何你需要做的事情。 (2认同)