动态创建一个结构体。

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

Go creating a structure dynamically

问题

这个脚本无法正常工作。我如何通过获取传入变量的类型(例如proc.ReadStat的类型是*linux.Stat,可以通过reflect.TypeOf()显示)动态创建一个新的结构体?

package main

import (
    "fmt"
    "reflect"
    "log"
    "net/http"
    "encoding/json"
    "github.com/gorilla/mux"
    proc "github.com/c9s/goprocinfo/linux"
)

func sysinfo(w http.ResponseWriter, r *http.Request) {
    sstat, _ := proc.ReadStat("/proc/stat")
    sdiskstats, _ := proc.ReadDiskStats("/proc/diskstats")
    sloadavg, _ := proc.ReadLoadAvg("/proc/loadavg")
    smeminfo,_ := proc.ReadMemInfo("/proc/meminfo")
    smounts, _ := proc.ReadMounts("/proc/mounts")
    snetstat, _ := proc.ReadNetStat("/proc/net/netstat")
    sdevstat, _ := proc.ReadNetworkStat("/proc/net/dev")
    ssockstat, _ := proc.ReadSockStat("/proc/net/sockstat")
    svmstat, _ := proc.ReadVMStat("/proc/vmstat")

    type Info struct {
        stat       reflect.TypeOf(sstat)
        diskstats  reflect.TypeOf(sdiskstats)
        loadavg    reflect.TypeOf(sloadavg)
        meminfo    reflect.TypeOf(smeminfo)
        mounts     reflect.TypeOf(smounts)
        netstat    reflect.TypeOf(snetstat)
        devstat    reflect.TypeOf(sdevstat)
        sockstat   reflect.TypeOf(ssockstat)
        vmstat     reflect.TypeOf(svmstat)
    }

    type infos []Info

    info := infos{
        Info{
            stat:       reflect.TypeOf(sstat),
            diskstats:  reflect.TypeOf(sdiskstats),
            loadavg:    reflect.TypeOf(sloadavg),
            meminfo:    reflect.TypeOf(smeminfo),
            mounts:     reflect.TypeOf(smounts),
            netstat:    reflect.TypeOf(snetstat),
            devstat:    reflect.TypeOf(sdevstat),
            sockstat:   reflect.TypeOf(ssockstat),
            vmstat:     reflect.TypeOf(svmstat),
        },
    }

    json.NewEncoder(w).Encode(info)
}

func main() {
    router := mux.NewRouter().StrictSlash(true)
    router.HandleFunc("/", sysinfo)
    log.Fatal(http.ListenAndServe(":8080", router))
}

以上是翻译好的代码部分。

英文:

This script does not work. How may I create a new struc dynamically by getting the types of incoming variables like proc.ReadStat ? (type of proc.ReadStat is *linux.Stat as shown by reflect.TypeOf() )

package main

import (
    "fmt"
	"reflect"
    //"html"
    "log"
    "net/http"
    //"time"
	"encoding/json"
    "github.com/gorilla/mux"
	proc "github.com/c9s/goprocinfo/linux"
)



func sysinfo(w http.ResponseWriter, r *http.Request) {


    sstat, _ := proc.ReadStat("/proc/stat")
    sdiskstats, _ := proc.ReadDiskStats("/proc/diskstats")
    sloadavg, _ := proc.ReadLoadAvg("/proc/loadavg")
    smeminfo,_ := proc.ReadMemInfo("/proc/meminfo")
    smounts, _ := proc.ReadMounts("/proc/mounts")
    snetstat, _ := proc.ReadNetStat("/proc/net/netstat")
    sdevstat, _ := proc.ReadNetworkStat("/proc/net/dev")
    ssockstat, _ := proc.ReadSockStat("/proc/net/sockstat")
    svmstat, _ := proc.ReadVMStat("/proc/vmstat")

t   /* type Info interface {
        stat      *linux.Stat
        diskstats []linux.DiskStat
        loadavg   *linux.LoadAvg
        meminfo   *linux.MemInfo
        mounts    *linux.Mounts
        netstat   *linux.NetStat
        devstat   []linux.NetworkStat
        sockstat  *linux.SockStat 
	    vmstat    *linux.VMStat
    }*/
    type Info struct {
        stat       reflect.TypeOf(sstat)
        diskstats  reflect.TypeOf(sdiskstats)
        loadavg    reflect.TypeOf(sloadavg)
        meminfo    reflect.TypeOf(smeminfo)
        mounts     reflect.TypeOf(smounts)
        netstat    reflect.TypeOf(snetstat)
        devstat    reflect.TypeOf(sdevstat)
        sockstat   reflect.TypeOf(ssockstat)
	    vmstat     reflect.TypeOf(svmstat)
    }

    type infos []Info

	
	infos := info{
		stat : sstat,
		diskstats : sdiskstats,
		loadavg : sloadavg,
		meminfo : smeminfo,
		mounts : smounts,
		netstat : snetstat,
		devstat : sdevstat,
		sockstat : ssockstat,
		vmstat : svmstat,
	}
	
    json.NewEncoder(w).Encode(infos)
	
	
}

func main() {

    router := mux.NewRouter().StrictSlash(true)
    router.HandleFunc("/", sysinfo)
    log.Fatal(http.ListenAndServe(":8080", router))
	
}

答案1

得分: 1

在静态类型语言中(Go 是其中之一),类型信息(变量、字段等的类型信息)必须在编译时存在,所以你不能像这样做:

type Info struct {
    stat       reflect.TypeOf(sstat)
}

因为 reflect.TypeOf() 是一个在运行时执行的函数。如果你不知道某个东西的类型,可以使用 interface{},但是编译器将无法进行编译时类型检查。

由于你只想要编组结果,你可以将字段的类型设置为 interface{}。还要注意,字段名必须是公开的(必须以大写字母开头),才能包含在 JSON 输出中。

所以尝试以下代码:

type Info struct {
    Stat       interface{}
    Diskstats  interface{}
    Loadavg    interface{}
    Meminfo    interface{}
    Mounts     interface{}
    Netstat    interface{}
    Devstat    interface{}
    Sockstat   interface{}
    Vmstat     interface{}
}

type infos []Info

infos := info{
    Stat : sstat,
    Diskstats : sdiskstats,
    Loadavg : sloadavg,
    Meminfo : smeminfo,
    Mounts : smounts,
    Netstat : snetstat,
    Devstat : sdevstat,
    Sockstat : ssockstat,
    Vmstat : svmstat,
}

json.NewEncoder(w).Encode(infos)

注意,你也可以使用简单的 map[string]interface{}

infos := map[string]interface{}{
    "stat" : sstat,
    "diskstats" : sdiskstats,
    "loadavg" : sloadavg,
    "meminfo" : smeminfo,
    "mounts" : smounts,
    "netstat" : snetstat,
    "devstat" : sdevstat,
    "sockstat" : ssockstat,
    "vmstat" : svmstat,
}
json.NewEncoder(w).Encode(infos)

另外,请不要忘记处理错误:存储返回的错误并检查它们是否为 nil

英文:

In statically typed languages (Go is one of them) type info (of variables, fields etc.) have to be present and compile-time, so you can't do something like:

type Info struct {
    stat       reflect.TypeOf(sstat)
}

Because reflect.TypeOf() is a function which will run at run-time. If you don't know the type of something, you may use interface{}, but then you won't get any compile-time type checking from the compiler.

Since you just want to marshal the results, you can use interface{} as the type of the fields. Also note that field names must be exported (must start with a capital letter) in order to be included in JSON output.

So try the following:

type Info struct {
    Stat       interface{}
    Diskstats  interface{}
    Loadavg    interface{}
    Meminfo    interface{}
    Mounts     interface{}
    Netstat    interface{}
    Devstat    interface{}
    Sockstat   interface{}
    Vmstat     interface{}
}

type infos []Info

infos := info{
    Stat : sstat,
    Diskstats : sdiskstats,
    Loadavg : sloadavg,
    Meminfo : smeminfo,
    Mounts : smounts,
    Netstat : snetstat,
    Devstat : sdevstat,
    Sockstat : ssockstat,
    Vmstat : svmstat,
}

json.NewEncoder(w).Encode(infos)

Note that you could also just use a simple map[string]interface{}:

infos := map[string]interface{}{
    "stat" : sstat,
    "diskstats" : sdiskstats,
    "loadavg" : sloadavg,
    "meminfo" : smeminfo,
    "mounts" : smounts,
    "netstat" : snetstat,
    "devstat" : sdevstat,
    "sockstat" : ssockstat,
    "vmstat" : svmstat,
}
json.NewEncoder(w).Encode(infos)

Also please do not forget about and do not omit error handling: store returned errors and check whether they are nil!

huangapple
  • 本文由 发表于 2015年11月20日 18:32:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/33824410.html
匿名

发表评论

匿名网友

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

确定