2017-03-27 15 views
0

オブジェクトAにフィールドがnet.Dialerであるとします。私はnet.Dialerのカスタム実装をオブジェクトAに提供して、Dialメソッドを補完したいと思います。これはGoで可能か?私はそうのようなembedded fieldsを使用しようとしている: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 

答えて

1

あなたがエラーを取得していますcustomDialernet.Dialerは2つの異なるタイプであり、互換的に使用できないためです。 Goでの埋め込みは、他のオブジェクト指向言語でのクラス継承と同じではないので、あなたがしようとしていることを助けません。

この場合には、ポリモーフィズム/ダックタイピングのようなGoインターフェイスを使用し、Goのインターフェイスは暗黙的に飽和されているため、既存のタイプがvirtueによって実装する新しいインターフェイスを定義できます新たに定義されたインタフェースと同じシグネチャを持つメソッドを持つことです。

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

+0

私はそれを正しく読んでいる場合は、残念ながら、 'net.Dialer'は、構造体として定義されて、答えを感謝していないインタフェース:https://golang.org/pkg/net /#Dialerまた、オブジェクトAを制御することはできないので、Dialerのパブリックメソッドである 'Dial'と' DialContext'を含む新しいインタフェースを使用するように変更することはできません。 –

+1

'A'を制御できない場合は' Dialer'インターフェースを割り当てることはできません。またGoで 'net.Dialer'以外のものを 'net'型のフィールドに割り当てることはできません。 Dialer' ...次に最も良いことは、オブジェクト 'A'をラップし、' Dial'を呼び出す前に何をしなくてもいいことです。 – mkopriva

+0

はい、私はあなたが正しいと思う、ラッピングAは現時点で私の唯一の選択肢のようだ。フィードバックをお寄せいただきありがとうございます! –

関連する問題