-2

假设我们有 2 个结构共享一个名称和用途相同但大小不同的属性:

type (
    L16 struct {
        Length uint16
    }

    L32 struct {
        Length uint32
    }
)

目标是使这些结构具有GetLength具有完全相同签名和实现的方法:

func (h *L16) GetLength() int {
    return int(h.Length)
}

func (h *L32) GetLength() int {
    return int(h.Length)
}

——但要避免对每个结构重复实现。

所以我尝试:

type (

    LengthHolder interface {
        GetLength() int
    }

    LengthHolderStruct struct {
        LengthHolder
    }

    L16 struct {
        LengthHolderStruct
        Length uint16
    }

    L32 struct {
        LengthHolderStruct
        Length uint32
    }

)

func (h *LengthHolderStruct) GetLength() int {
    return int(h.Length)
}

- 但错误与h.Length undefined (type *LengthHolderStruct has no field or method Length).

我们该怎么做呢?

4

1 回答 1

3

毫不客气的回答是,你不能,你不应该。只需在每个结构上实现该方法,让您和其他维护者的未来感到高兴。

无论如何,假设您绝对必须这样做,当然嵌入类型对嵌入类型一无所知,因此您无法从.LengthLengthHolderStruct

就个人而言,我认为@mh-cbon 的回答是一个不错的妥协。为了提供替代方案,您可以通过将字段声明为嵌入式结构上的 an 并使用类型开关(在 bin 中引发类型安全),以一种非常丑陋的方式解决这个问题。Lengthinterface{}

我不会在我的生产系统中使用下面的代码,但是你去吧:

func main() {
    l16 := L16{
        LengthHolderStruct: LengthHolderStruct{
            Length: uint16(200), 
            // but nothing stops you from setting uint32(200)
        },
    }
    fmt.Println(l16.GetLength())
}

type (
    LengthHolder interface {
        GetLength() int
    }

    LengthHolderStruct struct {
        Length interface{}
    }

    L16 struct {
        LengthHolderStruct
    }

    L32 struct {
        LengthHolderStruct
    }
)

func (h *LengthHolderStruct) GetLength() int {
    switch t := h.Length.(type) {
    case uint16:
        return int(t)
    case uint32:
        return int(t)
    }
    return 0
}

一旦语言获得类型参数,您的问题就会有不同的答案:

type Constraint interface {
     type uint16, uint32
     // or `~uint16 | ~uint32` with type sets
}

type LX[T Constraint] struct {
    Length T
}

func (h *LX[T]) GetLength() int {
    return int(h.Length)
}

func main() {
    lx := LX[uint16]{
        Length: uint16(200),
    }
    fmt.Println(lx.GetLength()) // 200
}

Go2 游乐场:https ://go2goplay.golang.org/p/nDZxPlXhP6H

于 2021-07-23T12:44:15.633 回答