我正在golang中为json处理器编写一个快速的ssh配置。我有以下结论:
type SshConfig struct {
Host string
Port string
User string
LocalForward string
...
}
我正在循环遍历我的ssh配置文件的每一行,并在空格上拆分行并检查要更新的属性。
if split[0] == "Port" {
sshConfig.Port = strings.Join(split[1:], " ")
}
有没有办法检查属性是否存在然后动态设置?
答案 0 :(得分:3)
使用reflect包按名称设置字段:
// setField sets field of v with given name to given value.
func setField(v interface{}, name string, value string) error {
// v must be a pointer to a struct
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.Elem().Kind() != reflect.Struct {
return errors.New("v must be pointer to struct")
}
// Dereference pointer
rv = rv.Elem()
// Lookup field by name
fv := rv.FieldByName(name)
if !fv.IsValid() {
return fmt.Errorf("not a field name: %s", name)
}
// Field must be exported
if !fv.CanSet() {
return fmt.Errorf("cannot set field %s", name)
}
// We expect a string field
if fv.Kind() != reflect.String {
return fmt.Errorf("%s is not a string field", name)
}
// Set the value
fv.SetString(value)
return nil
}
这样称呼:
var config SshConfig
...
err := setField(&config, split[0], strings.Join(split[1:], " "))
if err != nil {
// handle error
}
答案 1 :(得分:0)
您可以使用reflect包在运行时动态检查结构。请参阅docs和blog。
但是,如果您只想将文件读入结构,最好使用map[string]string
之类的东西。在运行时检查地图要清晰得多(例如,您可以range
检查地图,检查成员资格和......在一行中。)
m := make(map[string]string)
...
m[split[0]] = strings.Join(split[1:], " ")
答案 2 :(得分:0)
我最终在类型上定义了一个方法,并使用该方法的输入来返回我想要的属性。不太理想,但是简单明了,效果很好。
type PinMap struct {
Relay101 map[string]int `json:"192.168.1.101"`
Relay102 map[string]int `json:"192.168.1.102"`
}
// GetMap Allow dyanamic access of PinMap while maintaining struct
func (pm PinMap) GetMap(ip string) map[string]int {
switch ip {
case "192.168.1.101":
return pm.Relay101
case "192.168.1.102":
return pm.Relay102
default:
return pm.Relay101 // should probably throw and error
}
}
然后我使用如下代码:
relayPinMap := pumps.pinMap.GetMap(relayID)
golang还是很陌生的,所以请让我知道这是否是不好的做法-如果有充分的理由会拒绝回答。
还请注意,这对我来说有点麻烦,但是我需要它来工作,而且我必须在几分钟内使其工作。我认为最好是将类型设为map[string]map[string]int
,即,如果需要的话,在需要动态访问时使用映射而不是结构。