一. 终端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(¶mHost, "host", "unknown", "host name")
flag.IntVar(¶mPort, "port", 8080, "host port")
flag.BoolVar(¶mDaemon, "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(¶mUrl, "url", "http://0.0.0.0:8080/dl", "下载地址")
cmdDown.StringVar(¶mOut, "out", "~/download", "输出路径")
cmdRun.StringVar(¶mCfg, "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