背景是要根据 不同的 op 解析字符串到 不同的结构体,然后再执行相应的操作。
你当然够可以通过 if else 这样来枚举,但是这样不是很优雅。
通过定义 var OpArgsMap = make(map[string]OP) 把 op 和 结构体类型映射起来就优雅多了。
package resource
import (
"stardb-cli/resource/mysql"
"stardb-cli/resource/proxy"
)
type OP interface {
Do() error
}
// 操作函数与参数结构体的map,key应该与json文件中的"op"相同
var OpArgsMap = make(map[string]OP)
// 注册所有操作
func RegisterOperations() {
// mysql
OpArgsMap["mysql_env_check"] = &mysql.ArgsMysqlEnvCheck{}
OpArgsMap["mysql_install"] = &mysql.ArgsMysqlInstall{}
OpArgsMap["mysql_repl"] = &mysql.ArgsMysqlInstall{}
// proxy
OpArgsMap["proxy_env_check"] = &proxy.ArgsProxyEnvCheck{}
OpArgsMap["proxy_install"] = &proxy.ArgsProxyInstall{}
}
type ArgsMysqlEnvCheck struct {
Port uint16 `mapstructure:"port"`
DownloadUrl string `mapstructure:"download_url"`
BaseDir string `mapstructure:"base_dir"`
}
func (a *ArgsMysqlEnvCheck) Do() error {
fmt.Printf("In the Do of ArgsMysqlEnvCheck")
......
}
type ArgsMysqlInstall struct {
Port uint16 `mapstructure:"port"`
Version string `mapstructure:"version"`
DownloadUrl string `mapstructure:"download_url"`
BaseDir string `mapstructure:"base_dir"`
Cnf string `mapstructure:"cnf"`
}
func (a *ArgsMysqlInstall) Do() error {
fmt.Printf("In the Do of ArgsMysqlInstall")
......
}
// 反序列化参数
RegisterOperations()
import "github.com/spf13/viper"
g.VP = viper.New()
op := g.VP.GetString("op")
argStruct, ok := OpArgsMap[op]
if err := g.VP.UnmarshalKey("args", argStruct); err != nil {
.......
}