【问题标题】:Golang Function Call in Map地图中的 Golang 函数调用
【发布时间】:2016-08-16 09:43:23
【问题描述】:

我是 GO Programming 的新手。这是场景:-

存在一个如下所示的 JSON 文件:-

{
        "template": "linuxbase1",
        "checkname": ["check_disk"],
        "checkmethod": ["check_disk"]
}

我正在将这些数据解组到一个结构中:-

package func1

import (
        "io/ioutil"
        "os"
        "encoding/json"
        "fmt"
)

type pluginfunc func() string
type Plugindata struct {
        Template string `json:"template"`
        Checkname []string `json:"checkname"`
        Checkmethod []pluginfunc `json:"checkmethod"`
}

var (
        Templatepath = "json_sample1.json"
        Templateitems Plugindata
)

func Gettemplatedata() {
        tdata, err := ioutil.ReadFile(Templatepath)
        if err != nil {
                fmt.Printf("Unable to read file %s. Error - %v\n",Templatepath, err.Error())
                os.Exit(3)
        }
        json.Unmarshal(tdata, &Templateitems)
}

“check_disk”功能在这里:-

package func1

func check_disk() string {
        return "Called check_disk"
}

这是带有 main() 的程序:-

package main

import (
        "fmt"
        "checksexpt/func1"
)

func main() {
        func1.Gettemplatedata()
        fmt.Printf("Templateitems in Main() => %v\n",func1.Templateitems)
        for index,funcname := range func1.Templateitems.Checkmethod {
                fmt.Printf("%d = %s\n",index,funcname())
        }

}

正如预期的那样,当我运行 main();我看到了错误:-

Templateitems in Main() => {linuxbase1 [check_cpu check_disk] [<nil> <nil>]}
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x40115e]

goroutine 1 [running]:
panic(0x50e980, 0xc82000a100)
        /opt/go/src/runtime/panic.go:481 +0x3e6

所以,我试图从 JSON 文件中获取一个字符串并将其视为函数调用。那显然失败了!但是,这里的主要限制是必须从 JSON 文件中选择函数名称。我怎样才能做到这一点 ?我知道我可以按如下方式创建静态地图:-

type checkfunc func() string
var (
        Templateitems = map[string]map[string]checkfunc {
                "linuxbase1": {
                        "check_disk": check_disk,
                },
        }
)

所以,像 Templateitems["linuxbase1"]["check_disk"]() 这样的调用就可以了。但是,我不想创建任何这样的静态地图,因为该地图中的元素需要不断增长。对此有何想法?

【问题讨论】:

    标签: json function dictionary go


    【解决方案1】:

    没有直接的方法可以直接从 JSON 值解析函数。此外,您不能使用字符串值来引用变量。所以字符串check_cpu不能直接引用同名函数。

    您可以做的是按原样解析 json 字符串并为函数提供全局映射。这样,您可以像这样调用您的函数:

    var funcMap = map[string]pluginfunc{
        "check_disk": check_disk,
        "check_cpu": check_cpu
    }
    

    在您的 main 循环中:

    for index, funcname := range func1.Templateitems.Checkmethod {
            fmt.Printf("%d = %s\n", index, funcMap[funcname]())
    }
    

    但是,如果您确实需要将值放入结构中,您可以尝试从json.Unmarshaler 接口实现UnmarshalJSON。一个简单的例子是:

    type pf map[string]pluginfunc
    
    type Plugindata struct {
            Template string `json:"template"`
            Checkname []string `json:"checkname"`
            Checkmethod pf `json:"checkmethod"`
    }
    
    func (p *pf) UnmarshalJSON(data []byte) error {
        d := []string{}
        if err := json.Unmarshal(data, &d); err != nil {
            return err
        }
        *p = make(pf)
        for _, s := range d {
            (*p)[s] = funcMap[s]
        }
        return nil
    }
    
    var funcMap = pf{
        "check_disk": check_disk,
        "check_cpu": check_cpu
    }
    
    func main() {
        json.Unmarshal(tdata, &Templateitems)
        for k, f := range Templateitems.Checkmethod {
            fmt.Printf("%s -- %s\n", k, f())
        }
    }
    

    Working code

    请注意,这种方法不像第一种方法那样易读或简单,它仍然依赖于函数映射。

    你可以阅读更多关于json.Unmarshalerhere的信息。

    【讨论】:

      猜你喜欢
      • 2015-02-25
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 2018-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多