cli - 构建强大命令行程序的工具箱 (4)

获取 cli

cli 开源在 github 上,欢迎大家前去 star :-)

使用go get获取

go get github.com/mkideal/cli

上一篇介绍了CommandContext对象,以及构建多层子命令的方法.本片将介绍一个构建http服务的栗子。本篇示例代码由 goplus 生成

goplus new -t http httpd

示例代码

package main

import (
    "fmt"
    "os"

    "github.com/mkideal/cli"
)

func main() {
    if err := cli.Root(root,
        cli.Tree(help),
        cli.Tree(daemon),
        cli.Tree(api,
            cli.Tree(ping),
        ),
    ).Run(os.Args[1:]); err != nil {
        fmt.Println(err)
    }
}

//------
// root
//------
var root = &cli.Command{
    Fn: func(ctx *cli.Context) error {
        ctx.WriteUsage()
        return nil
    },
}

//------
// help
//------
var help = &cli.Command{
    Name:        "help",
    Desc:        "display help",
    CanSubRoute: true,
    HTTPRouters: []string{"/v1/help"},
    HTTPMethods: []string{"GET"},

    Fn: cli.HelpCommandFn,
}

//--------
// daemon
//--------
type daemonT struct {
    cli.Helper
    Port uint16 `cli:"p,port" usage:"http port" dft:"8080"`
}

func (t *daemonT) Validate(ctx *cli.Context) error {
    if t.Port == 0 {
        return fmt.Errorf("please don't use 0 as http port")
    }
    return nil
}

var daemon = &cli.Command{
    Name: "daemon",
    Desc: "startup app as daemon",
    Argv: func() interface{} { return new(daemonT) },
    Fn: func(ctx *cli.Context) error {
        argv := ctx.Argv().(*daemonT)
        if argv.Help {
            ctx.WriteUsage()
            return nil
        }

        //NOTE: remove following line will disable debug mode
        cli.EnableDebug()

        addr := fmt.Sprintf(":%d", argv.Port)
        cli.Debugf("http addr: %s", addr)

        r := ctx.Command().Root()
        if err := r.RegisterHTTP(ctx); err != nil {
            return err
        }
        return r.ListenAndServeHTTP(addr)
    },
}

//-----
// api
//-----
var api = &cli.Command{
    Name: "api",
    Desc: "display all api",
    Fn: func(ctx *cli.Context) error {
        ctx.String("Commands:\n")
        ctx.String("    ping\n")
        return nil
    },
}

//------
// ping
//------
var ping = &cli.Command{
    Name: "ping",
    Desc: "ping server",
    Fn: func(ctx *cli.Context) error {
        ctx.String("pong\n")
        return nil
    },
}

daemon命令

示例中,负责启动http服务的是daemon命令。注意代码的77~81这5行:

r := ctx.Command().Root()
if err := r.RegisterHTTP(ctx); err != nil {
    return err
}
return r.ListenAndServeHTTP(addr)

这里通过ctx.Command().Root()获取到根命令,然后调用根命令的RegisterHTTP方法。这个方法主要是注册各个命令的自定义路由.
在上面这个示例中只为help命令指定了自定义的路由

HTTPRouters: []string{"/v1/help"},

别的命令

示例中别的命令的实现都非常简单,比如api及其子命令ping,都只是输出一个字符串.

启动服务

cd到代码目录,编译然后运行

$> go build -o httpd
$> ./httpd daemon -p 8080

然后就可以在浏览器上访问
http:127.0.0.1:8080/api/ping
或者使用curl

curl http:127.0.0.1:8080/api/ping

如果你在本直接运行

./httpd api ping

你会发现这和使用http访问得到的输出是一样的。

由于help指令置顶了自定义路由/v1/help,所以处理可以通过标准路由

http://127.0.0.1:8080/help

访问外,还可以通过自定义路由访问

http://127.0.0.1:8080/v1/help

结语

使用cli创建http服务就这么简单.只需要调用根命令的ListenAndServeHTTP方法就可以了,当然如果你要是使用自定义路由,这需要调用根命令的RegisterHTTP方法。启动http服务后,其他所有命令都可以通过http调用了。
github上参看http的栗子.

共 0 个回复