GO: 查找/扫描结构体/函数

huangapple go评论73阅读模式
英文:

GO: find/scan for structs/functions

问题

在Go语言中,可以通过名称、标签或接口等条件来查找结构体或函数吗?例如类似于命令行任务/动词的方式?

func cmd1() {
    ...
}

func cmd2() {
    ...
}

...

func cmdN() {
}

func main() {
    // 检查 os.Args 并根据参数调用 cmd{X}() 函数。
    ...
}

我不介意具体的机制,也不介意最终的目标是函数还是结构体——目标是通过约定而不需要任何样板代码来实现某种工作方式。

英文:

Is it possible in GO to find structs or functions by criteria such as name, tag or interface? i.e something along the lines of command line tasks/verbs? i.e:

func cmd1() {
    ...
}

func cmd2() {
    ...
}

...

func cmdN() {
}

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

I don't mind what the exact mechanism is and if the final targets are functions or structs - the goal is to get something working by convention without any boilerplate code.

答案1

得分: 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 + " 不是一个有效的命令")
        return
    }

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

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

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

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

func main() {
    flag.Parse()

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

或者你可以使用映射的方式实现:

package main

import (
    "flag"
    "fmt"
)

func cmd1() {
    fmt.Println("命令 1")
}

func cmd2() {
    fmt.Println("命令 2")
}

func cmd3() {
    fmt.Println("命令 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) + " 命令未找到")
    }
}

希望对你有帮助!

英文:

You could use reflection

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))
}

or you could use a map.

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")
    }
}

答案2

得分: 0

我在《如何在Go中使用反射测试函数集合?》中使用了类似的方法。

思路是列出并找到所有所需的函数,对于我的情况来说,是某个结构体类型的函数:

stype := reflect.ValueOf(s)
for _, fname := range funcNames {
    sfunc := stype.MethodByName(fname)
    // 无参数 => 空的 Value 切片
    ret := sfunc.Call([]reflect.Value{})
}
英文:

I used a similar approach in "How to test a collection of functions by reflection in Go?"

The idea is to list and find all the functions needed, in my case, functions for a certain struct type:

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

huangapple
  • 本文由 发表于 2014年9月27日 23:23:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/26076165.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定