├── .gitignore ├── go.mod ├── examples └── main.go ├── process.go ├── Help.go ├── Ini.go ├── readme.md └── Console.go /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /.idea 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ctfang/command 2 | -------------------------------------------------------------------------------- /examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/ctfang/command" 6 | "log" 7 | ) 8 | 9 | func main() { 10 | app := command.New() 11 | 12 | app.AddBaseOption(command.ArgParam{ 13 | Name: "TEST", 14 | Description: "显示帮助信息", 15 | Default: "false", 16 | Call: nil, 17 | }) 18 | 19 | app.AddCommand(Echo{}) 20 | app.AddCommand(Hello{}) 21 | app.Run() 22 | } 23 | 24 | type Echo struct { 25 | } 26 | 27 | func (Echo) Configure() command.Configure { 28 | return command.Configure{ 29 | Name: "echo", 30 | Description: "示例命令 echo", 31 | } 32 | } 33 | 34 | func (Echo) Execute(input command.Input) { 35 | log.Println("hello command") 36 | } 37 | 38 | type Hello struct { 39 | } 40 | 41 | func (Hello) Configure() command.Configure { 42 | return command.Configure{ 43 | Name: "hello", 44 | Description: "示例命令 hello", 45 | Input: command.Argument{ 46 | // Argument参数为必须的输入的,不输入不执行 47 | Argument: []command.ArgParam{ 48 | {Name: "name", Description: "命令后面第一个参数"}, 49 | {Name: "sex", Description: "命令后面第二个参数"}, 50 | }, 51 | // 匹配字符参数,匹配不到就是 value = false 52 | Has: []command.ArgParam{ 53 | {Name: "one", Description: "是否拥有one字符串"}, 54 | {Name: "-t", Description: "是否拥有 -t 字符串"}, 55 | }, 56 | // 可选的参数,不输入也能执行 57 | Option: []command.ArgParam{ 58 | {Name: "age", Description: "年龄选项参数", Default: "18"}, 59 | {Name: "age", Description: "年龄选项参数", Default: "24"}, 60 | }, 61 | }, 62 | } 63 | } 64 | 65 | func (Hello) Execute(input command.Input) { 66 | fmt.Println("hello") 67 | fmt.Println("名称:", input.GetArgument("name")) 68 | fmt.Println("性别:", input.GetArgument("sex")) 69 | fmt.Println("年龄 :", input.GetOption("age")) 70 | fmt.Println("是否输入了 one :", input.GetHas("one")) 71 | fmt.Println("是否输入了 -t :", input.GetHas("-t")) 72 | } 73 | -------------------------------------------------------------------------------- /process.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "os/signal" 9 | "path/filepath" 10 | "runtime" 11 | "strconv" 12 | "strings" 13 | "syscall" 14 | ) 15 | 16 | func GetRootPath() string { 17 | dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 18 | if err != nil { 19 | dir, _ = os.Getwd() 20 | return dir 21 | } 22 | return dir 23 | } 24 | 25 | func GetRootFile() string { 26 | paths, fileName := filepath.Split(os.Args[0]) 27 | ext := filepath.Ext(fileName) 28 | abs := strings.TrimSuffix(fileName, ext) 29 | 30 | return paths + abs 31 | } 32 | 33 | /* 34 | 保存pid 35 | 命令key 唯一标识 36 | */ 37 | func SavePidToFile(key string) { 38 | pid := os.Getpid() 39 | path := GetRootFile() + "_" + key + ".lock" 40 | _ = ioutil.WriteFile(path, []byte(fmt.Sprintf("%d", pid)), 0666) 41 | } 42 | 43 | /* 44 | 删除pid文件 45 | 命令key 唯一标识 46 | */ 47 | func DeleteSavePidToFile(key string) { 48 | path := GetRootFile() + "_" + key + ".lock" 49 | os.Remove(path) 50 | } 51 | 52 | /* 53 | 获取pid 54 | 命令key 唯一标识 55 | */ 56 | func GetPidForFile(key string) int { 57 | path := GetRootFile() + "_" + key + ".lock" 58 | str, err := ioutil.ReadFile(path) 59 | if err != nil { 60 | return 0 61 | } 62 | pid, err := strconv.Atoi(string(str)) 63 | if err != nil { 64 | return 0 65 | } 66 | return pid 67 | } 68 | 69 | func ListenStopSignal(handle func(sig os.Signal)) { 70 | sigs := make(chan os.Signal, 1) 71 | 72 | signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) 73 | 74 | go func() { 75 | sig := <-sigs 76 | handle(sig) 77 | }() 78 | } 79 | 80 | /* 81 | 停止进程 82 | 命令key 唯一标识 83 | windows 不发送信号,直接停止 84 | */ 85 | func StopSignal(key string) error { 86 | pid := GetPidForFile(key) 87 | if pid == 0 { 88 | return errors.New("找不到pid记录文件") 89 | } 90 | // 通过pid获取子进程 91 | pro, err := os.FindProcess(pid) 92 | if err != nil { 93 | return errors.New("找不到进程信息,文件过期") 94 | } 95 | err = pro.Signal(syscall.SIGINT) 96 | if err != nil { 97 | if runtime.GOOS == "windows" { 98 | err = pro.Kill() 99 | if err != nil { 100 | return nil 101 | } 102 | DeleteSavePidToFile(key) 103 | } 104 | return nil 105 | } 106 | return nil 107 | } 108 | -------------------------------------------------------------------------------- /Help.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strconv" 7 | ) 8 | 9 | type Help struct { 10 | console *Console 11 | } 12 | 13 | func (Help) Configure() Configure { 14 | return Configure{ 15 | Name: "help", 16 | Description: "帮助命令", 17 | Input: Argument{}, 18 | } 19 | } 20 | 21 | func (h Help) Execute(input Input) { 22 | fmt.Println("Usage:") 23 | fmt.Println(" command [options] [arguments] [has]") 24 | fmt.Println("Base Options:") 25 | for _, ArgParam := range h.console.baseOption { 26 | h.EchoSpace(" -"+ArgParam.Name, 25) 27 | fmt.Println(ArgParam.Description) 28 | } 29 | fmt.Println("Available commands:") 30 | // 命令排序 31 | var keys []string 32 | var macLen int 33 | for cmdName, _ := range h.console.MapCommand { 34 | keys = append(keys, cmdName) 35 | tempLen := len(cmdName) 36 | if tempLen > macLen { 37 | macLen = tempLen 38 | } 39 | } 40 | sort.Strings(keys) 41 | macLen += 4 42 | for _, cmdName := range keys { 43 | h.EchoSpace(" "+cmdName, macLen) 44 | kv := h.console.MapCommand[cmdName] 45 | fmt.Println(kv.CommandConfig.Description) 46 | } 47 | } 48 | 49 | // 字符串不足,空格补充输出 50 | func (Help) EchoSpace(str string, mac int) { 51 | strCon := strconv.Itoa(mac) 52 | fmt.Printf("%-"+strCon+"s", str) 53 | } 54 | 55 | // 某个命令需要帮助时 56 | func (h Help) HelpExecute(con Configure) { 57 | fmt.Println("Usage:") 58 | fmt.Print(" ", con.Name) 59 | for _, ArgParam := range con.Input.Argument { 60 | fmt.Print(" <", ArgParam.Name, ">") 61 | } 62 | fmt.Println() 63 | for _, ArgParam := range con.Input.Option { 64 | if len(ArgParam.Default) >= 1 { 65 | h.EchoSpace(" -"+ArgParam.Name, 25) 66 | fmt.Println("= " + ArgParam.Default) 67 | } 68 | } 69 | fmt.Println("Arguments:") 70 | for _, ArgParam := range con.Input.Argument { 71 | h.EchoSpace(" "+ArgParam.Name, 25) 72 | fmt.Println(ArgParam.Description) 73 | } 74 | fmt.Println("Option:") 75 | for _, ArgParam := range con.Input.Option { 76 | h.EchoSpace(" -"+ArgParam.Name, 25) 77 | fmt.Println(ArgParam.Description) 78 | } 79 | for _, ArgParam := range h.console.baseOption { 80 | h.EchoSpace(" -"+ArgParam.Name, 25) 81 | fmt.Println(ArgParam.Description) 82 | } 83 | fmt.Println("Has:") 84 | for _, ArgParam := range con.Input.Has { 85 | h.EchoSpace(" "+ArgParam.Name, 25) 86 | fmt.Println(ArgParam.Description) 87 | } 88 | fmt.Println("Description:") 89 | fmt.Println(" ", con.Description) 90 | } 91 | -------------------------------------------------------------------------------- /Ini.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "os" 7 | "path/filepath" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | type ini struct { 13 | config map[string]interface{} 14 | } 15 | 16 | func (i *ini) GetFileName(path string)string { 17 | return filepath.Join(path) 18 | } 19 | 20 | func (i *ini) Load(path string) { 21 | i.config = make(map[string]interface{}) 22 | 23 | path = i.GetFileName(path) 24 | 25 | file, err := os.Open(path) 26 | if err != nil && os.IsNotExist(err) { 27 | return 28 | } 29 | defer file.Close() 30 | 31 | r := bufio.NewReader(file) 32 | prefix := "" 33 | 34 | for { 35 | b, _, err := r.ReadLine() 36 | if err != nil { 37 | if err == io.EOF { 38 | break 39 | } 40 | panic(err) 41 | } 42 | 43 | //去除单行属性两端的空格 44 | s := strings.TrimSpace(string(b)) 45 | if len(s) == 0 { 46 | continue 47 | } 48 | 49 | firstStr := s[0:1] 50 | // 注释 51 | if firstStr == ";" { 52 | continue 53 | } else if firstStr == "[" { 54 | // new map 55 | index := strings.Index(s, "]") 56 | if index < 0 { 57 | continue 58 | } 59 | prefix = string(b[1:index]) + "." 60 | } else { 61 | key, value := i.getKeyValue(s) 62 | if key != "" { 63 | i.config[prefix+key] = value 64 | } 65 | } 66 | 67 | } 68 | } 69 | 70 | func (i *ini) getKeyValue(s string) (string, interface{}) { 71 | //判断等号=在该行的位置 72 | index := strings.Index(s, "=") 73 | if index < 0 { 74 | return "", "" 75 | } 76 | //取得等号左边的key值,判断是否为空 77 | key := strings.TrimSpace(s[:index]) 78 | if len(key) == 0 { 79 | return "", "" 80 | } 81 | 82 | //取得等号右边的value值,判断是否为空 83 | value := strings.TrimSpace(s[index+1:]) 84 | if len(value) == 0 { 85 | return key, "" 86 | } 87 | 88 | // 值转换 89 | if value=="true" { 90 | return key,true 91 | }else if value=="false" { 92 | return key,false 93 | }else if value[0:1]=="\"" { 94 | return key,value[1:len(value)-1] 95 | }else if strings.Index(value, ".")>0 { 96 | float,_ := strconv.ParseFloat(value, 32) 97 | return key,float 98 | }else{ 99 | num,_ := strconv.Atoi(value) 100 | return key,num 101 | } 102 | } 103 | 104 | // 获取值 105 | func (i *ini) GetInt(key string, value int) int { 106 | va, ok := i.config[key] 107 | if !ok { 108 | return value 109 | } 110 | value, ok = va.(int) 111 | if ok { 112 | return value 113 | } 114 | return value 115 | } 116 | 117 | // 获取值 118 | func (i *ini) GetString(key string, value string) string { 119 | va, ok := i.config[key] 120 | if !ok { 121 | return value 122 | } 123 | value, ok = va.(string) 124 | if ok { 125 | return value 126 | } 127 | return value 128 | } 129 | 130 | 131 | // 获取值 132 | func (i *ini) GetBool(key string, value bool) bool { 133 | va, ok := i.config[key] 134 | if !ok { 135 | return value 136 | } 137 | value, ok = va.(bool) 138 | if ok { 139 | return value 140 | } 141 | return value 142 | } 143 | 144 | // 判断是否存在 145 | func (i *ini) Has(key string) bool { 146 | _, ok := i.config[key] 147 | return ok 148 | } 149 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## golang cli 应用封装 2 | 3 | 命令行应用,基本调用封装、参数获取 4 | 5 | ~~~~gotemplate 6 | go get github.com/ctfang/command 7 | ~~~~ 8 | 9 | ### 基础使用 10 | 11 | 代码在 go get github.com/ctfang/command/examples/main.go 12 | 13 | ~~~~go 14 | package main 15 | 16 | import ( 17 | "github.com/ctfang/command" 18 | "log" 19 | ) 20 | 21 | func main() { 22 | app := command.New() 23 | app.AddCommand(Echo{}) 24 | app.AddCommand(Hello{}) 25 | app.Run() 26 | } 27 | // Echo 需要实现接口 CommandInterface 28 | type Echo struct { 29 | } 30 | 31 | func (Echo) Configure() command.Configure { 32 | return command.Configure{ 33 | Name:"echo", 34 | Description:"示例命令 echo", 35 | } 36 | } 37 | 38 | func (Echo) Execute(input command.Input) { 39 | log.Println("echo command") 40 | } 41 | ~~~~ 42 | 43 | 运行 44 | ~~~~ 45 | go run main.go 46 | ------------------------------------- 47 | Usage: 48 | command [options] [arguments] [has] 49 | Base Has Param: 50 | -d 守护进程启动 51 | -h 显示帮助信息参数 52 | Available commands: 53 | echo 示例命令 echo 54 | help 帮助命令 55 | 56 | go run main.go echo 57 | ------------------------------------- 58 | 2019/03/25 17:01:46 hello command 59 | ~~~~ 60 | 61 | ### 设置参数 62 | 参数分为三种类型,必须参数,可选参数,匹配参数 63 | 64 | ~~~~go 65 | type Hello struct { 66 | } 67 | 68 | func (Hello) Configure() command.Configure { 69 | return command.Configure{ 70 | Name: "hello", 71 | Description: "示例命令 hello", 72 | Input: command.Argument{ 73 | // Argument参数为必须的输入的,不输入不执行 74 | Argument: []command.ArgParam{ 75 | {Name: "name", Description: "命令后面第一个参数"}, 76 | {Name: "sex", Description: "命令后面第二个参数"}, 77 | }, 78 | // 匹配字符参数,匹配不到就是 value = false 79 | Has: []command.ArgParam{ 80 | {Name: "one", Description: "是否拥有one字符串"}, 81 | {Name: "-t", Description: "是否拥有 -t 字符串"}, 82 | }, 83 | // 可选的参数,不输入也能执行 84 | Option: []command.ArgParam{ 85 | {Name: "age", Description: "年龄选项参数"}, 86 | }, 87 | }, 88 | } 89 | } 90 | 91 | func (Hello) Execute(input command.Input) { 92 | fmt.Println("hello") 93 | fmt.Println("名称:",input.GetArgument("name")) 94 | fmt.Println("性别:",input.GetArgument("sex")) 95 | fmt.Println("年龄 :",input.GetOption("age")) 96 | fmt.Println("是否输入了 one :",input.GetHas("one")) 97 | fmt.Println("是否输入了 -t :",input.GetHas("-t")) 98 | } 99 | ~~~~ 100 | #### 查看帮助命令 101 | ~~~~ 102 | go run main.go hello -h 103 | ------------------------------------- 104 | Usage: 105 | hello 106 | Arguments: 107 | name 命令后面第一个参数 108 | sex 命令后面第二个参数 109 | Option: 110 | -age 年龄选项参数 111 | Has: 112 | one 是否拥有one字符串 113 | -t 是否拥有 -t 字符串 114 | -d 守护进程启动 115 | -h 显示帮助信息 116 | Description: 117 | 示例命令 hello 118 | 119 | ------------------------------------- 120 | go run main.go hello 李四 男 -age=18 -t one 121 | ------------------------------------- 122 | hello 123 | 名称: 李四 124 | 性别: 男 125 | 年龄 : 18 126 | 是否输入了 one : true 127 | 是否输入了 -t : true 128 | 129 | ~~~~ 130 | #### 自定义 131 | 132 | * 自带了help命令,可以友好输出帮助列表 133 | * 为每个命令都加上了 -d,可以转化为守护进程执行 134 | * 为每个命令都加上了 -h,和显示帮助详情 135 | * 以上都支持覆盖,只要在需要覆盖的命令,重复定义即可 136 | 137 | ##### 默认值 138 | 139 | 虽然可以在执行命令时候,赋值默认值,例如: 140 | ~~~~ 141 | name := input.GetOption("name") 142 | if name == "" { 143 | name = "李四" 144 | } 145 | ~~~~ 146 | 但是,对于多环境运行,总归是不方便;特别是在一些命令需要非常多的参数时,总不能修改代码在运行。 147 | 148 | 为了应付这种问题,command,允许 添加一个 config.ini 配置文件,设置默认值 149 | ~~~~ 150 | app := command.New() 151 | 152 | app.SetConfig("config.ini") 153 | app.IniConfig() 154 | 155 | app.Run() 156 | ~~~~ 157 | config.ini 文件内容 158 | ~~~~ 159 | ; 这个是注释 160 | url="127.0.0.1:8080" 161 | ; 名称默认值 162 | name="张三" 163 | ~~~~ 164 | 将会输出 [张三] 165 | ~~~~ 166 | name := input.GetOption("name") 167 | if name == "" { 168 | name = "李四" 169 | } 170 | fmt.Println(name) 171 | ~~~~ 172 | 173 | 174 | -------------------------------------------------------------------------------- /Console.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | type Console struct { 11 | MapCommand map[string]MapCommand 12 | configPath string 13 | config ini 14 | baseOption []ArgParam 15 | run MapCommand 16 | } 17 | 18 | // 创建一个命令应用 19 | func New() Console { 20 | return Console{ 21 | MapCommand: map[string]MapCommand{}, 22 | baseOption: []ArgParam{ 23 | { 24 | Name: "h", 25 | Description: "显示帮助信息", 26 | Default: "false", 27 | Call: helpHandle, 28 | }, 29 | }, 30 | } 31 | } 32 | 33 | func helpHandle(val string, c *Console) (string, bool) { 34 | if val != "false" { 35 | help := Help{c} 36 | help.HelpExecute(c.run.CommandConfig) 37 | return val, false 38 | } 39 | return val, true 40 | } 41 | 42 | func helpDaemon(val string, c *Console) bool { 43 | return false 44 | } 45 | 46 | // 添加通用参数 47 | func (c *Console) AddBaseOption(param ArgParam) { 48 | c.baseOption = append([]ArgParam{param}, c.baseOption...) 49 | } 50 | 51 | type Command interface { 52 | Configure() Configure 53 | Execute(input Input) 54 | } 55 | 56 | type Configure struct { 57 | // 命令名称 58 | Name string 59 | // 说明 60 | Description string 61 | // 输入定义 62 | Input Argument 63 | } 64 | 65 | type MapCommand struct { 66 | Command Command 67 | CommandConfig Configure 68 | } 69 | 70 | // 参数操作 71 | type Input struct { 72 | console *Console 73 | // 是否有参数 【名称string】默认值bool 74 | Has map[string]bool 75 | // 必须输入参数 【命令位置】【赋值名称】默认值 76 | Argument map[string]string 77 | // 可选输入参数 【赋值名称(开头必须是-)】默认值 78 | Option map[string][]string 79 | // 启动文件 80 | FilePath string 81 | } 82 | 83 | // 参数存储 84 | type ArgParam struct { 85 | Name string // 名称 86 | Description string // 说明 87 | Default string // 默认值 88 | Call func(val string, c *Console) (string, bool) // 获取值的时候执行, return false中断 89 | } 90 | 91 | // 参数设置结构 92 | type Argument struct { 93 | // 是否有参数 【名称string】 94 | Has []ArgParam 95 | // 必须输入参数 【命令位置】【赋值名称】默认值 96 | Argument []ArgParam 97 | // 可选输入参数 【赋值名称(开头必须是-)】默认值 98 | Option []ArgParam 99 | } 100 | 101 | func (c *Console) IniConfig() { 102 | path := c.getConfig() 103 | c.config = ini{} 104 | c.config.Load(path) 105 | } 106 | 107 | var cacheInput = make(map[string]map[string]bool) 108 | 109 | // 载入命令 110 | func (c *Console) AddCommand(Command Command) { 111 | var SaveCom MapCommand 112 | 113 | CmdConfig := Command.Configure() 114 | for key, ArgParam := range CmdConfig.Input.Option { 115 | if c.config.Has(ArgParam.Name) { 116 | CmdConfig.Input.Option[key].Default = c.config.GetString(ArgParam.Name, "") 117 | } 118 | } 119 | 120 | SaveCom.CommandConfig = CmdConfig 121 | SaveCom.Command = Command 122 | c.MapCommand[CmdConfig.Name] = SaveCom 123 | } 124 | 125 | func (c *Console) getConfig() string { 126 | return c.configPath 127 | } 128 | 129 | func (c *Console) SetConfig(path string) { 130 | c.configPath = path 131 | } 132 | 133 | // 载入命令 134 | func (c *Console) Run() { 135 | defaultCmdName := "help" 136 | _, ok := c.MapCommand[defaultCmdName] 137 | if !ok { 138 | // 注册帮助命令 139 | c.AddCommand(Help{c}) 140 | } 141 | 142 | argsLen := len(os.Args) 143 | var args []string 144 | var cmdName string 145 | if argsLen < 2 { 146 | cmdName = defaultCmdName 147 | } else { 148 | cmdName = os.Args[1] 149 | args = os.Args[2:] 150 | _, ok1 := c.MapCommand[cmdName] 151 | if !ok1 { 152 | fmt.Println("不存在的命令:" + cmdName) 153 | cmdName = defaultCmdName 154 | } 155 | } 156 | 157 | // 执行到这里,必须有命令 158 | c.run = c.MapCommand[cmdName] 159 | input := Input{ 160 | console: c, 161 | Has: map[string]bool{}, 162 | Argument: map[string]string{}, 163 | Option: map[string][]string{}, 164 | FilePath: os.Args[0], 165 | } 166 | err := input.Parsed(c.run.CommandConfig.Input, args) 167 | if err != nil { 168 | return 169 | } 170 | 171 | c.run.Command.Execute(input) 172 | } 173 | 174 | // 参数解析 175 | func (i *Input) Parsed(Config Argument, args []string) error { 176 | // 选项值 177 | i.ParsedOptions(Config, args) 178 | 179 | for _, ArgParam := range Config.Has { 180 | for _, strArg := range args { 181 | if ArgParam.Name == strArg { 182 | i.Has[ArgParam.Name] = true 183 | } 184 | } 185 | _, ok := i.Has[ArgParam.Name] 186 | if !ok { 187 | i.Has[ArgParam.Name] = false 188 | } 189 | } 190 | 191 | // 必须值 192 | lenArgument := len(args) 193 | for mustInt, kv := range Config.Argument { 194 | if lenArgument <= mustInt { 195 | // 不存在,报错,并且输出帮助命令 196 | fmt.Println("必须输入参数:" + kv.Name) 197 | return errors.New("必须输入参数:" + kv.Name) 198 | } else { 199 | i.Argument[kv.Name] = args[mustInt] 200 | } 201 | } 202 | return nil 203 | } 204 | 205 | // 解析选项值 206 | func (i *Input) ParsedOptions(Config Argument, args []string) { 207 | for _, kv := range i.console.baseOption { 208 | Config.Option = append(Config.Option, kv) 209 | } 210 | for _, kv := range Config.Option { 211 | i.Option[kv.Name] = make([]string, 0) 212 | } 213 | var strArgKy, strValue string 214 | for _, strArg := range args { 215 | startIndex := strings.Index(strArg, "-") 216 | if startIndex == 0 { 217 | stopIndex := strings.Index(strArg, "=") 218 | if stopIndex < 0 { 219 | // 不存在 = 号 220 | strArgKy = strArg[startIndex+1:] 221 | strValue = "" 222 | } else { 223 | strArgKy = strArg[startIndex+1 : stopIndex] 224 | strValue = strArg[stopIndex+1:] 225 | } 226 | if strArgKy != "" { 227 | if _, ok := i.Option[strArgKy]; !ok { 228 | i.Option[strArgKy] = make([]string, 0) 229 | } 230 | i.Option[strArgKy] = append(i.Option[strArgKy], strValue) 231 | } 232 | } 233 | } 234 | // 添加默认值 235 | for _, kv := range Config.Option { 236 | if len(i.Option[kv.Name]) == 0 { 237 | // 支持多个默认值 238 | for _, kv2 := range Config.Option { 239 | if kv.Name == kv2.Name { 240 | i.Option[kv.Name] = append(i.Option[kv.Name], kv2.Default) 241 | } 242 | } 243 | } 244 | // 执行回调, 使用回调赋值 245 | if kv.Call != nil { 246 | var stop bool 247 | i.Option[kv.Name][0], stop = kv.Call(i.Option[kv.Name][0], i.console) 248 | if stop == false { 249 | os.Exit(0) 250 | } 251 | } 252 | } 253 | } 254 | 255 | // 参数 256 | func (i *Input) GetHas(key string) bool { 257 | value, ok := i.Has[key] 258 | if !ok { 259 | return false 260 | } 261 | return value 262 | } 263 | 264 | // 参数 265 | func (i *Input) GetArgument(key string) string { 266 | value, ok := i.Argument[key] 267 | if !ok { 268 | return "" 269 | } 270 | return value 271 | } 272 | 273 | // 参数 274 | func (i *Input) GetOption(key string) string { 275 | value, ok := i.Option[key] 276 | if !ok { 277 | return "" 278 | } 279 | return value[0] 280 | } 281 | 282 | func (i *Input) GetOptions(key string) []string { 283 | value, ok := i.Option[key] 284 | if !ok { 285 | return []string{} 286 | } 287 | return value 288 | } 289 | 290 | // 是否后台启动 291 | func (i *Input) IsDaemon() bool { 292 | value, ok := i.Has["-d"] 293 | if !ok { 294 | return false 295 | } 296 | return value 297 | } 298 | 299 | func (i *Input) GetFilePath() string { 300 | return i.FilePath 301 | } 302 | --------------------------------------------------------------------------------