Go命令行程序

一. 终端IO

1. 命令行参数:

func main() {
   all := os.Args      // AppName + Args
   args := os.Args[1:] //Args

   fmt.Println(all)
   fmt.Println(args)
   os.Exit(1)
}

2. os.Stdin:

  • os.Stdin类型为*File,而*File实现了io.Reader接口。
func main() {
   buf := make([]byte, 1024)
   n, _ := os.Stdin.Read(buf) //标准输入
   os.Stdout.Write(buf[:n])   //标准输出
}

3. fmt.Scanln:

  • 将命令行输入内容按空格分隔按次序存放到相应参数内,直到碰到换行。
  • fmt.Scanln调用Fscanln(os.Stdin, a...),即对os.Stdin的封装。
func main() {
   var id int
   var name string
   fmt.Scanln(&id, &name)
   fmt.Printf("id=%d,name=%q\n", id, name)
}

4. fmt.Sscanf:

  • 按照format参数定义的分割方式,将字符串依次赋值给相应参数。
func main() {
   var id int;var name string
   fmt.Sscanf("1001/bj/Tom", "%d/%s", &id, &name)  //从左向右截取
   fmt.Printf("id=%d,name=%q\n", id, name)
}

5. bufio.Reader

func main() {
   stdin := bufio.NewReader(os.Stdin) //os.Stdin类型为*File
   input, _ := stdin.ReadString('\n')
   fmt.Println(input)
}

二. Flag包

1. 简单模式

可使用flag.Type(...)flag.TypeVar(...)两种方式接收参数。

  • flag参数可以是-paramName=val-paramName val(不支持bool类型)形式。
  • bool类型参数支持1, 0, t, f, T,F,true, false, TRUE, FALSE, True, False形式。
  • int支持十进制、八进制、十六进制形式,如077、0xff等。
// 使用:./cli -host "192.168.1.100" -port 3306 -daemon true (对bool值无效)
//      ./cli -host="192.168.1.100" -port=3306 -daemon=true
func SimpleFlag() {
   // 1. 定义
   paramHost := flag.String("host", "127.0.0.1", "主机名")
   paramPort := flag.Int("port", 8080, "端口")
   paramDaemon := flag.Bool("daemon", false, "守护进程")

   // 2. 解析
   flag.Parse()

   // 3. 应用
   fmt.Printf("%s:%d(daemon=%t)\r\n", *paramHost, *paramPort, *paramDaemon)
}
// 使用:./cli -host "192.168.1.100" -port 3306 -daemon=true
//      ./cli -host="192.168.1.100" -port=3306 -daemon=true
func SimpleVar() {
   var (
      paramHost   string
      paramPort   int
      paramDaemon bool
   )
   // 1. 定义
   flag.StringVar(&paramHost, "host", "unknown", "host name")
   flag.IntVar(&paramPort, "port", 8080, "host port")
   flag.BoolVar(&paramDaemon, "daemon", false, "daemon server")

   // 2. 解析
   flag.Parse()

   // 3. 应用
   fmt.Printf("%s:%d(daemon=%t)\r\n", paramHost, paramPort, paramDaemon)
}

2. 自定义类型

  • 比如可定义一个数组参数来接收N个数据,自定义类型,须实现flag.Value接口。
//实现了Value接口
type StringArray []string

func newStringArray(items []string, p *[]string) *StringArray {
   *p = items
   return (*StringArray)(p)
}

func (s *StringArray) Set(val string) error {
   *s = strings.Split(val, ",")
   return nil
}

func (s *StringArray) String() string {
   return fmt.Sprintf("result: [%s]\r\n", strings.Join([]string(*s)," "))
}

// 编译: go build -o cli
// 运行: ./cli -items="java,golang"
func main(){
   var items []string
   foo:=newStringArray([]string{}, &items)
   flag.Var(foo, "items", "以逗号分割的字符串数组`string array`")
   flag.Parse()

   fmt.Println(items)
   fmt.Printf(foo.String())
}

3. 二级命令

// 4. 二级命令
// 使用:./cli get -url https://github.com/myfile -out ~/soft
//     ./cli run -config /etc/app.yml
func SubCommand() {
   // 1. 二级命令
   cmdDown := flag.NewFlagSet("get", flag.ExitOnError) //下载
   cmdRun := flag.NewFlagSet("run", flag.ExitOnError)  //运行

   var (
      paramUrl string
      paramOut string
      paramCfg string
   )

   // 2. 命令参数
   cmdDown.StringVar(&paramUrl, "url", "http://0.0.0.0:8080/dl", "下载地址")
   cmdDown.StringVar(&paramOut, "out", "~/download", "输出路径")
   cmdRun.StringVar(&paramCfg, "config", "/etc/cli.conf", "配置文件")

   // 3. 解析命令
   switch os.Args[1] {
   case "get":
      err := cmdDown.Parse(os.Args[2:])
      if err != nil {
         log.Panic(err)
      }
   case "run":
      err := cmdRun.Parse(os.Args[2:])
      if err != nil {
         log.Panic(err)
      }
   default:
      os.Exit(1)
   }

   // 4. 应用解析
   if cmdDown.Parsed() {
      fmt.Printf("url=%s\r\nout=%s\r\n", paramUrl, paramOut)
   }
   if cmdRun.Parsed() {
      fmt.Printf("config=%s\r\n", paramCfg)
   }
}

4. 打印帮助

// ./cli -help
func PrintUsage() {
   var (
      host string
      port string
      help bool
   )
   // 1. 定义命令
   flag.StringVar(&host, "host", "127.0.0.1", "主机名")
   flag.StringVar(&port, "port", "8080", "端口号")
   flag.BoolVar(&help, "help", false, "帮助文档")

   // 2. 编写帮助文档
   flag.Usage = func() {
      fmt.Fprintf(os.Stderr, `Cli 是一个命令行演示客户端

Version: Cli 1.0
Usage: Cli [-data] [-host host] [-port port] [-help the cli usage]

Options:
`)
      flag.PrintDefaults()
   }

   // 3. 解析命令
   flag.Parse()

   // 4. 打印帮助
   if help {
      flag.Usage()
   }
}

三. 守护进程

  • 可使用如./app -daemon=true的形式,将一个Web或其他应用启动为一个守护进程。
// 参考:github.com/icattlecoder/godaemon
var (
	name   string
	port   string
	daemon bool
)

func init() {
	flag.StringVar(&name, "name", "gin_server", "App名称")
	flag.StringVar(&port, "port", "8080", "端口号")
	flag.BoolVar(&daemon, "daemon", false, "守护进程")

	if !flag.Parsed() {
		flag.Parse()
	} else {
		fmt.Println("错误")
		return
	}

	if daemon {
		args := os.Args[1:]
		for i := 0; i < len(args); i++ {
			if args[i] == "-daemon=true" {
				args[i] = "-daemon=false"
				break
			}
		}
		cmd := exec.Command(os.Args[0], args...)
		cmd.Start()
		fmt.Printf("【%s】服务已启动,port=%s, [PID]=%d\r\n", name,port, cmd.Process.Pid)
		os.Exit(0)
	}
}

// 编译: go build -o ./gin_server main.go
// 启动: ./gin_server -name="GinServer" -daemon=true
// 测试: curl 0.0.0.0:8080/index
func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/index", func(rw http.ResponseWriter, req *http.Request) {
		rw.Write([]byte("测试成功!\n"))
	})
	log.Fatalln(http.ListenAndServe(":" + port, mux))
}

参考:
https://www.kancloud.cn/liupengjie/go/570085
https://www.jianshu.com/p/f9cf46a4de0e
https://github.com/urfave/cli

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值