在不同结构之间共享方法实现
Sharing method implementations between different structs
假设我们有 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)
.
出错
我们怎么做?
粗鲁的回答是你不能你不应该。只需在每个结构上实现该方法,让未来的您和其他维护者满意。
无论如何,假设你绝对必须这样做,当然 embedded 类型对 embedding 类型一无所知所以你不能从 LengthHolderStruct
.
引用 Length
就我个人而言,我认为 @mh-cbon answer 是一个不错的折衷方案。为了提供替代方案,您可以通过在嵌入式结构上将 Length
字段声明为 interface{}
并使用类型开关,以 非常丑陋 的方式解决这个问题(将类型安全扔进垃圾箱)。
我不会在我的生产系统中使用以下代码,但你可以:
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
}
假设我们有 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)
.
我们怎么做?
粗鲁的回答是你不能你不应该。只需在每个结构上实现该方法,让未来的您和其他维护者满意。
无论如何,假设你绝对必须这样做,当然 embedded 类型对 embedding 类型一无所知所以你不能从 LengthHolderStruct
.
Length
就我个人而言,我认为 @mh-cbon answer 是一个不错的折衷方案。为了提供替代方案,您可以通过在嵌入式结构上将 Length
字段声明为 interface{}
并使用类型开关,以 非常丑陋 的方式解决这个问题(将类型安全扔进垃圾箱)。
我不会在我的生产系统中使用以下代码,但你可以:
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
}