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

mkideal · 2016-03-22 13:36:07 · 3486 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2016-03-22 13:36:07 的主题,其中的信息可能已经有所发展或是发生改变。

获取 cli

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

使用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的栗子.


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3486 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传