【问题标题】:GO: find/scan for structs/functionsGO:查找/扫描结构/函数
【发布时间】:2014-09-28 00:15:16
【问题描述】:

在 GO 中是否可以通过名称、标签或接口等条件来查找结构或函数?即类似于命令行任务/动词的东西?即:

func cmd1() {
    ...
}

func cmd2() {
    ...
}

...

func cmdN() {
}

func main() {
    // Inspect os.Args and call cmd{X}() based on args.
    ...
}

我不介意确切的机制是什么,以及最终目标是函数还是结构 - 目标是在没有任何样板代码的情况下让某些东西按照惯例工作。

【问题讨论】:

  • 如果你把它变成上面例子的最小答案,我会接受它。
  • 当然,但在我的例子中,这些函数有一个结构体作为接收器。

标签: go


【解决方案1】:

你可以使用反射

package main

import (
    "flag"
    "fmt"
    "reflect"
)

var cmd command

type command struct{}

func (c command) execute(name string) {
    v := reflect.ValueOf(c)

    cmd := v.MethodByName(name)
    if !cmd.IsValid() {
        fmt.Println(name + " not a command")
        return
    }

    cmd.Call([]reflect.Value{})
}

func (c command) Cmd1() {
    fmt.Println("command 1")
}

func (c command) Cmd2() {
    fmt.Println("command 2")
}

func (c command) Cmd3() {
    fmt.Println("command 3")
}

func main() {
    flag.Parse()

    cmd.execute(flag.Arg(0))
}

或者你可以使用地图。

package main

import (
    "flag"
    "fmt"
)

func cmd1() {
    fmt.Println("command 1")
}

func cmd2() {
    fmt.Println("command 2")
}

func cmd3() {
    fmt.Println("command 3")
}

var funcs = map[string]func(){
    "cmd1": cmd1,
    "cmd2": cmd2,
    "cmd3": cmd3,
}

func main() {
    flag.Parse()

    if f, ok := funcs[flag.Arg(0)]; ok {
        f()
    } else {
        fmt.Println(flag.Arg(0) + " command not found")
    }
}

【讨论】:

  • 我们的想法是获得一个约定俗成的习语,而不必手动维护这样的列表,在我的特定情况下,该列表将增长到大约 500 项。
  • 不幸的是,这是唯一的方法。
【解决方案2】:

我在“How to test a collection of functions by reflection in Go?”中使用了类似的方法

这个想法是列出并找到所有需要的函数,在我的例子中,是某种结构类型的函数:

stype := reflect.ValueOf(s)
for _, fname := range funcNames {
    sfunc := stype.MethodByName(fname)
    // no parameter => empty slice of Value
    ret := sfunc.Call([]reflect.Value{})

【讨论】:

猜你喜欢
  • 2016-08-17
  • 1970-01-01
  • 2020-02-15
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多