有 2 个 struct A B,分别有自己的 New 方法 NewA(),NewB(),并且已经实现了 interface C { Scan ()} 想通过命令行传参,在 main 方法使用的时候选择实例化 A or B 并且执行 scan()
run.go A
目前的写法是用 switch 判断,感觉不太对头,有优雅的写法吗?
switch svc {
case "A":
a := NewA()
go func(c C) {
c.Scan()
}(a)
case "B":
b := NewB()
go func(c C) {
c.Scan()
}(b)
}
1
ncbdwss 16 天前
package main
import ( "fmt" ) type C interface { Scan() } type A struct{} func NewA() *A { return &A{} } func (a *A) Scan() { fmt.Println("A Scan") } type B struct{} func NewB() *B { return &B{} } func (b *B) Scan() { fmt.Println("B Scan") } // 工厂函数,返回不同的类型 func NewInstance(svc string) (C, error) { switch svc { case "A": return NewA(), nil case "B": return NewB(), nil default: return nil, fmt.Errorf("invalid service: %s", svc) } } func main() { svc := "A" // 可以通过命令行参数获取 svc // 通过工厂函数选择实例化对象 c, err := NewInstance(svc) if err != nil { fmt.Println("Error:", err) return } // 启动并执行 Scan() go func(c C) { c.Scan() }(c) // 阻塞,避免主程序提前退出 select {} } 说明: NewInstance(svc string):通过传入的 svc 字符串来决定实例化 A 或 B ,返回 C 类型接口。 在 main 函数中,通过 NewInstance 获取具体的实例并执行 Scan() 方法。 使用 go 协程来异步执行 Scan() 方法。 通过 select{} 保证主程序不会提前退出。 这样做的好处: 通过工厂模式将实例化逻辑集中管理,避免了 switch 语句的重复使用。 如果以后需要添加更多的服务,只需在 NewInstance 函数中增加对应的 case ,而不需要修改 main 函数的核心逻辑,增加了可扩展性。 这种写法比直接使用 switch 更加优雅、清晰,并且具有更好的可扩展性。 |
2
zong400 OP |
3
stormer 16 天前 1
手动撸了个,你也可以改为 struct 方式
```go type CmdFunc func(args) const cmds = map[string]CmdFunc{ "A":A, "B":B, } func A(args){ } func B(args){ } func main(){ if(len(os.args)<=2){ //err exit } cmd:=os.args(1) fun,ok:=cmds[cmd] if ok { fun(os.args) } } ``` |
4
xzysaber 10 天前
也可以写一个容器,注册不同的类型,例如 A,B 。
传参就到容器中获取。 本质是一个 map 存取。 |