Golang中如何为不同结构体使用相同的方法
Golang中如何为不同结构体使用相同的方法 我有两个结构体,它们都拥有相同的方法:
func (r *myStruct1) DoThis() error {}
func (r *myStruct1) DoThat() error {}
func (r *myStruct2) DoThis() error {}
func (r *myStruct2) DoThat() error {}
我不喜欢这里的重复代码,因为它们实际上做的是同一件事,只是针对不同的结构体。有没有什么方法可以将其通用化?如果可以,能否提供一个代码示例?
2 回复
这被称为组合设计模式。
package main
import "fmt"
type myStruct1 struct {
method func()
}
type myStruct2 struct {
method func()
}
func doThis() {
fmt.Println("test")
}
func main() {
struct1 := myStruct1{
method: doThis,
}
struct2 := myStruct1{
method: doThis,
}
struct1.method()
struct2.method()
}
更多关于Golang中如何为不同结构体使用相同的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中可以通过接口和嵌入两种方式实现不同结构体共享相同方法。以下是具体实现:
方法1:使用接口定义通用行为
package main
import "fmt"
// 定义接口
type Doer interface {
DoThis() error
DoThat() error
}
// 结构体1
type myStruct1 struct {
Name string
}
// 结构体2
type myStruct2 struct {
ID int
}
// 通用实现函数
func commonDoThis(d Doer) error {
// 这里可以根据需要访问具体结构体的字段
fmt.Println("DoThis executed")
return nil
}
func commonDoThat(d Doer) error {
fmt.Println("DoThat executed")
return nil
}
// 为myStruct1实现接口
func (r *myStruct1) DoThis() error {
return commonDoThis(r)
}
func (r *myStruct1) DoThat() error {
return commonDoThat(r)
}
// 为myStruct2实现接口
func (r *myStruct2) DoThis() error {
return commonDoThis(r)
}
func (r *myStruct2) DoThat() error {
return commonDoThat(r)
}
func main() {
s1 := &myStruct1{Name: "test1"}
s2 := &myStruct2{ID: 123}
s1.DoThis()
s2.DoThat()
}
方法2:使用嵌入结构体
package main
import "fmt"
// 基础结构体包含通用方法
type BaseActions struct{}
func (b *BaseActions) DoThis() error {
fmt.Println("Base DoThis")
return nil
}
func (b *BaseActions) DoThat() error {
fmt.Println("Base DoThat")
return nil
}
// 结构体1嵌入BaseActions
type myStruct1 struct {
BaseActions
Name string
}
// 结构体2嵌入BaseActions
type myStruct2 struct {
BaseActions
ID int
}
// 如果需要覆盖方法
func (r *myStruct1) DoThis() error {
fmt.Printf("myStruct1 DoThis with Name: %s\n", r.Name)
return nil
}
func main() {
s1 := &myStruct1{Name: "struct1"}
s2 := &myStruct2{ID: 100}
s1.DoThis() // 使用覆盖的方法
s1.DoThat() // 使用嵌入的方法
s2.DoThis() // 使用嵌入的方法
s2.DoThat() // 使用嵌入的方法
}
方法3:使用函数组合
package main
import "fmt"
// 结构体定义
type myStruct1 struct {
Value string
}
type myStruct2 struct {
Value int
}
// 通用函数
func DoThisGeneric[T any](obj *T, getValue func(*T) string) error {
value := getValue(obj)
fmt.Printf("DoThis with value: %s\n", value)
return nil
}
func DoThatGeneric[T any](obj *T, getValue func(*T) string) error {
value := getValue(obj)
fmt.Printf("DoThat with value: %s\n", value)
return nil
}
// 具体结构体的方法
func (r *myStruct1) DoThis() error {
return DoThisGeneric(r, func(m *myStruct1) string {
return m.Value
})
}
func (r *myStruct1) DoThat() error {
return DoThatGeneric(r, func(m *myStruct1) string {
return m.Value
})
}
func (r *myStruct2) DoThis() error {
return DoThisGeneric(r, func(m *myStruct2) string {
return fmt.Sprintf("%d", m.Value)
})
}
func (r *myStruct2) DoThat() error {
return DoThatGeneric(r, func(m *myStruct2) string {
return fmt.Sprintf("%d", m.Value)
})
}
func main() {
s1 := &myStruct1{Value: "hello"}
s2 := &myStruct2{Value: 42}
s1.DoThis()
s2.DoThat()
}
方法4:Go 1.18+ 使用泛型
package main
import "fmt"
// 定义通用接口
type Doer interface {
DoThis() error
DoThat() error
}
// 通用结构体包装器
type GenericStruct[T any] struct {
Data T
doThis func(*T) error
doThat func(*T) error
}
func (g *GenericStruct[T]) DoThis() error {
return g.doThis(&g.Data)
}
func (g *GenericStruct[T]) DoThat() error {
return g.doThat(&g.Data)
}
// 创建具体实例的辅助函数
func NewMyStruct1(name string) Doer {
return &GenericStruct[myStruct1]{
Data: myStruct1{Name: name},
doThis: func(m *myStruct1) error {
fmt.Printf("myStruct1 DoThis: %s\n", m.Name)
return nil
},
doThat: func(m *myStruct1) error {
fmt.Printf("myStruct1 DoThat: %s\n", m.Name)
return nil
},
}
}
func NewMyStruct2(id int) Doer {
return &GenericStruct[myStruct2]{
Data: myStruct2{ID: id},
doThis: func(m *myStruct2) error {
fmt.Printf("myStruct2 DoThis: %d\n", m.ID)
return nil
},
doThat: func(m *myStruct2) error {
fmt.Printf("myStruct2 DoThat: %d\n", m.ID)
return nil
},
}
}
type myStruct1 struct {
Name string
}
type myStruct2 struct {
ID int
}
func main() {
s1 := NewMyStruct1("test")
s2 := NewMyStruct2(123)
s1.DoThis()
s1.DoThat()
s2.DoThis()
s2.DoThat()
}
嵌入结构体是最简洁的方式,接口方式更符合Go的惯用法,泛型方式在Go 1.18+中提供了更强的类型安全性。选择哪种方式取决于具体需求和Go版本。

