V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
zong400
V2EX  ›  Go 编程语言

菜鸟请教 interface 的使用

  •  
  •   zong400 · 16 天前 · 785 次点击

    有 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)
    }
    
    4 条回复    2024-12-13 10:28:22 +08:00
    ncbdwss
        1
    ncbdwss  
       15 天前
    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
        2
    zong400  
    OP
       15 天前
    @ncbdwss 虽然是 gpt 的,也感谢你
    我发现根本错的地方是我的 New 方法返回了 A ,所以 main 里面实例化的 a,b 类型错了
    应该返回 C 才对
    func NewA() C
    stormer
        3
    stormer  
       15 天前   ❤️ 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)
    }
    }
    ```
    xzysaber
        4
    xzysaber  
       9 天前
    也可以写一个容器,注册不同的类型,例如 A,B 。
    传参就到容器中获取。
    本质是一个 map 存取。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2735 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 08:04 · PVG 16:04 · LAX 00:04 · JFK 03:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.