dpevsxjn809817 2016-08-16 09:43
浏览 41

地图中的Golang函数调用

I am a newbie at GO Programming. Here is scenario :-

There exists a JSON file that looks like this :-

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

I am Unmarshalling this data into a structure :-

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
",Templatepath, err.Error())
                os.Exit(3)
        }
        json.Unmarshal(tdata, &Templateitems)
}

The "check_disk" function is here :-

package func1

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

This is the program with main() :-

package main

import (
        "fmt"
        "checksexpt/func1"
)

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

}

As expected, when I run main(); I see the error :-

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

So, I am trying to grab a string from the JSON file and treat it as a function call. That obviously fails ! But, the primary constraint here is that the function names have to be picked from the JSON file. How can I do this ? I know that I can create a static map as follows :-

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

So, A call like - Templateitems["linuxbase1"]["check_disk"]() would work just fine. But, I dont want to create any such static map as the elements in that map needs to keep growing. Any ideas on this?

  • 写回答

1条回答 默认 最新

  • dongtui0650 2016-08-16 10:56
    关注

    There is no direct way to parse a function directly from a JSON value. Also, you cannot use string values to refer to variables. So a string check_cpu would not be able to refer to the function with the same name directly.

    What you can do instead is parse the json string as is and have a global map for functions. That way, you can call your functions like so:

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

    In your main loop:

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

    If however, you really need to put the value in your structure, you can try implementing UnmarshalJSON from the json.Unmarshaler interface. A simple example would be:

    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
    ", k, f())
        }
    }
    

    Working code

    Note that this way is not as readable or simple as the first method and it still relies on a function map.

    You can read more about json.Unmarshaler here.

    评论

报告相同问题?

悬赏问题

  • ¥15 运动想象脑电信号数据集.vhdr
  • ¥15 三因素重复测量数据R语句编写,不存在交互作用
  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目