2016-08-16 4 views
1

Ich bin ein Neuling bei GO-Programmierung. Hier Szenario: -Golang Funktionsaufruf in Karte

Es existiert eine JSON-Datei, die wie folgt aussieht: -

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

Ich unmarshalling diese Daten in eine Struktur: -

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

Die "check_disk" -Funktion hier: -

package func1 

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

Dies ist das Programm mit 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()) 
     } 

} 

Wie erwartet, wenn ich main() ausführen; Ich sehe den Fehler: -

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 

Also, ich versuche, eine Zeichenfolge aus der JSON-Datei zu packen und es als Funktionsaufruf zu behandeln. Das scheitert natürlich! Die Hauptbedingung dafür ist jedoch, dass die Funktionsnamen aus der JSON-Datei ausgewählt werden müssen. Wie kann ich das machen ? Ich weiß, dass ich eine statische Karte erstellen, wie folgt: -

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

So Ein Anruf wie - Templateitems["linuxbase1"]["check_disk"]() würde gut funktionieren. Aber ich möchte keine solche statische Karte erstellen, da die Elemente in dieser Karte weiter wachsen müssen. Irgendwelche Ideen dazu?

Antwort

2

Es gibt keine direkte Möglichkeit, eine Funktion direkt aus einem JSON-Wert zu analysieren. Außerdem können Sie keine Zeichenfolgenwerte verwenden, um auf Variablen zu verweisen. Ein String check_cpu könnte also nicht direkt auf die gleichnamige Funktion verweisen.

Was Sie stattdessen tun können, ist die JSON-Zeichenfolge analysieren, wie es ist, und eine globale Zuordnung für Funktionen haben.

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

In Ihrer main Schleife: Auf diese Weise können Sie Ihre Funktionen wie so nennen

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

Wenn Sie jedoch wirklich brauchen, um den Wert in Ihrer Struktur zu setzen, können Sie versuchen UnmarshalJSON Umsetzung von die json.Unmarshaler Schnittstelle. Ein einfaches Beispiel wäre:

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

Beachten Sie, dass auf diese Weise nicht so lesbar oder einfach wie die erste Methode ist, und es stützt sich nach wie vor auf einer Funktionskarte. Sie können mehr über json.Unmarshalerhere lesen

Verwandte Themen