Extend struct in Go

huangapple go评论112阅读模式
英文:

Extend struct in Go

问题

假设对象A具有类型为net.Dialer的字段。我想为对象A提供一个自定义的net.Dialer实现,以增强Dial方法。在Go语言中是否可行?我尝试使用嵌入字段,代码如下:

  1. package main
  2. import (
  3. "net"
  4. "fmt"
  5. )
  6. type dialerConsumer struct {
  7. dialer net.Dialer
  8. }
  9. func (dc *dialerConsumer) use() error {
  10. conn, e := dc.dialer.Dial("tcp", "golang.org:http")
  11. if e != nil {
  12. return e
  13. }
  14. fmt.Printf("conn: %s\n", conn)
  15. return nil
  16. }
  17. type customDialer struct {
  18. net.Dialer
  19. }
  20. func main() {
  21. standardDialer := net.Dialer{}
  22. consumer := &dialerConsumer{
  23. dialer: standardDialer,
  24. }
  25. consumer.use()
  26. /*
  27. customDialer := customDialer{
  28. net.Dialer{},
  29. }
  30. consumer = &dialerConsumer{
  31. dialer: customDialer,
  32. }
  33. consumer.use()
  34. */
  35. }

然而,当我取消main函数中被注释掉的代码时,我会得到以下编译错误:

  1. 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:

  1. package main
  2. import (
  3. "net"
  4. "fmt"
  5. )
  6. type dialerConsumer struct {
  7. dialer net.Dialer
  8. }
  9. func (dc *dialerConsumer) use() error {
  10. conn, e := dc.dialer.Dial("tcp", "golang.org:http")
  11. if e != nil {
  12. return e
  13. }
  14. fmt.Printf("conn: %s\n", conn)
  15. return nil
  16. }
  17. type customDialer struct {
  18. net.Dialer
  19. }
  20. func main() {
  21. standardDialer := net.Dialer{}
  22. consumer := &dialerConsumer{
  23. dialer: standardDialer,
  24. }
  25. consumer.use()
  26. /*
  27. customDialer := customDialer{
  28. net.Dialer{},
  29. }
  30. consumer = &dialerConsumer{
  31. dialer: customDialer,
  32. }
  33. consumer.use()
  34. */
  35. }

However, when I uncomment the commented-out code in main, I get the following compilation error:

  1. src/test.go:38: cannot use customDialer (type customDialer) as type net.Dialer in field value

答案1

得分: 6

你之所以出现错误,是因为customDialernet.Dialer是两种不同的类型,不能互相替换使用。在Go语言中,嵌入不同于其他面向对象语言中的类继承,所以它不能帮助你实现你想要的功能。

在这种情况下,你可以使用Go语言的接口来实现类似多态/鸭子类型的功能。由于Go语言中的接口是隐式满足的,你可以定义一个新的接口,只要现有类型具有与新定义接口相同签名的方法,它就会自动实现该接口。

  1. // 已经由net.Dialer实现
  2. type Dialer interface {
  3. Dial(network, address string) (net.Conn, error)
  4. }
  5. type customDialer struct {
  6. *net.Dialer
  7. }
  8. func (cd *customDialer) Dial(network, address string) (net.Conn, error) {
  9. conn, err := cd.Dialer.Dial(network, address)
  10. if err != nil {
  11. return nil, err
  12. }
  13. fmt.Printf("conn: %s\n", conn)
  14. return conn, nil
  15. }
  16. // 现在dialer字段可以设置为*customDialer和net.Dialer
  17. type dialerConsumer struct {
  18. dialer Dialer
  19. }

链接: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.

  1. // already implemented by net.Dialer
  2. type Dialer interface {
  3. Dial(network, address string) (net.Conn, error)
  4. }
  5. type customDialer struct {
  6. *net.Dialer
  7. }
  8. func (cd *customDialer) Dial(network, address string) (net.Conn, error) {
  9. conn, err := cd.Dialer.Dial(network, address)
  10. if err != nil {
  11. return nil, err
  12. }
  13. fmt.Printf("conn: %s\n", conn)
  14. return conn, nil
  15. }
  16. // now the dialer field can be set to *customDialer and net.Dialer as well
  17. type dialerConsumer struct {
  18. dialer Dialer
  19. }

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

huangapple
  • 本文由 发表于 2017年3月27日 18:43:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/43044224.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定