英文:
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
!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论