菜鸟请教 interface 的使用

13 天前
 zong400

有 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)
}
737 次点击
所在节点    Go 编程语言
4 条回复
ncbdwss
13 天前
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 更加优雅、清晰,并且具有更好的可扩展性。
zong400
13 天前
@ncbdwss 虽然是 gpt 的,也感谢你
我发现根本错的地方是我的 New 方法返回了 A ,所以 main 里面实例化的 a,b 类型错了
应该返回 C 才对
func NewA() C
stormer
12 天前
手动撸了个,你也可以改为 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)
}
}
```
xzysaber
6 天前
也可以写一个容器,注册不同的类型,例如 A,B 。
传参就到容器中获取。
本质是一个 map 存取。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1095547

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX