2016-08-16 15 views
1

私はGOプログラミングの初心者です。ここではシナリオがある: - :私は構造にこのデータを非整列化していますGolang Function地図で呼び出し

{ 
     "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" 機能がある

は次のようになりますJSONファイルが存在しますここに: - :

-

package func1 

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

これは、メイン()を持つプログラムです

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"]()がうまく動作します。しかし、私はマップの要素が増え続ける必要があるので、そのような静的マップを作成したくありません。これに関するアイデア?

答えて

2

直接JSON値から関数を解析する方法はありません。また、文字列値を使用して変数を参照することはできません。したがって、文字列check_cpuは、同じ名前の関数を直接参照することはできません。

代わりに、json文字列をそのまま解析し、関数用のグローバルマップを作成します。そうすれば、あなたはそうのようなあなたの関数を呼び出すことができます。あなたのmainループでは

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

を:

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

しかし、あなたが本当にあなたの構造体に値を配置する必要がある場合は、あなたからUnmarshalJSONを実装してみてくださいjson.Unmarshalerインターフェイス。簡単な例は次のようになります。

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について詳しく読むことができます。

関連する問題