命令行启动服务的方式,在后端使用非常广泛,如果有写过C语言的同学相信不难理解这一点!在C语言中,我们可以根据argc和argv来获取和解析命令行的参数,从而通过不同的参数调取不同的方法,同时也可以用Usage来打印帮助信息了。

那么开始今天的话题之前,我们回顾一下在C语言中是如何解析传递的参数的。

示例代码:

#include <stdio.h>
#include <stdlib.h> // argc 为int型
// argv 为char指针数组,元素个数是argc,存放的是指向每一个参数的指针
int main(int argc, char *argv[])
{ printf("命令行参数个数: %d\n", argc);
printf("执行程序的名称:%s\n", argv[0]); int i = 1; // 从下标1开始获取,因为0代表的是程序名称 while(i < argc)
{
// 循环打印每个命令行的参数
printf("%s\n", argv[i]);
i++;
} return 0;
}

编译运行:

#gcc c_cli.c -o c_cli
./c_cli /usr/local/service/config /usr/local/service/log/service.log
命令行参数个数: 3
执行程序的名称:./c_cli
/usr/local/service/config
/usr/local/service/log/service.log

看完上面的例子,其实我们可以发现,上例中是C语言自带的参数解析,对于简单的参数构成还是可以使用的。下面我们再看一下Go语言os标准库的实现。

示例代码:

package main

import (
"fmt"
"os"
) func main() { var args = os.Args
fmt.Println(args) return
}

编译执行:

#go build go_flag.go
#./go_flag /usr/local/service/config /usr/local/service/log/service.log
[./go_flag /usr/local/service/config /usr/local/service/log/service.log]

上例中,我们可以看到os.Args返回一个数组,数组里面是我们命令行执行时,所传递的参数和程序名称。os自带的参数获取,对于简单的参数来说还能使用,如果参数复杂的情况下,那么解析起来就比较费劲的。这个时候,我们可以选择Go语言的flag标准库来帮我们处理命令行解析工作。

Flag包:https://golang.org/pkg/flag/

是Go语言提供的一个标准库,能够较为方便和灵活的解析命令行传递的参数。

flag有两种方式:

1、flag.Type,其中Type可以是:int、string、bool,float等类型,返回指针类型。

var port = flag.Int("port", 0, "相关描述")

参数1:flag的名称

参数2:flag的值,上例中默认值是0

参数3:flag的描述

2、flag.TypeVar,将类型绑定到一个变量上。

var port int
flag.IntVar(&port, "port", 0, "相关描述")

参数1:flag的值

参数2:flag的名称

参数3:flag的值,上例中默认值是0

参数4:flag的描述

示例代码:

package main

import (
"flag"
"fmt"
"os"
) var (
// 定义一个tcp端口号
tcp_port int // flag.Type(Name为Flag的名字,Value是Flag的值,Usage是Flag的提示信息)
port = flag.Int("port", 0, "服务端口设置参数为:-port=80")
config = flag.String("config", "", "配置文件配置参数为:-config=/usr/local/service/config")
logFile = flag.String("logfile", "", "日志文件配置参数为:-logfile=/usr/local/service/log/service.log")
// flag.Type返回的是指针类型,所以获取值为"*变量" ) func init() {
flag.IntVar(&tcp_port, "tcp_port", 0, "TCP服务端口描述: -tcp_port=2001")
flag.Usage = func() {
_, _ = fmt.Fprint(os.Stderr,
"cli : go_flag -port=8080 -config=/usr/local/service/config "+
"-logfile=/usr/local/service/log/service.log -tcp_port=2001\n")
flag.PrintDefaults()
} flag.Parse()
} func main() { if *port <= 0 {
flag.PrintDefaults()
os.Exit(1)
} if tcp_port <= 0 {
flag.PrintDefaults()
os.Exit(1)
} if *config == "" {
flag.PrintDefaults()
os.Exit(2)
} if *logFile == "" {
flag.PrintDefaults()
os.Exit(3)
} fmt.Printf("service tcp port : %d \n", tcp_port)
fmt.Printf("service port : %d \n", *port)
fmt.Printf("service config : %s \n", *config)
fmt.Printf("service logfile : %s \n", *logFile)
return
}

运行结果:

#go build go_flag.go
#./go_flag
-config string
配置文件配置参数为:-config=/usr/local/service/config
-logfile string
日志文件配置参数为:-logfile=/usr/local/service/log/service.log
-port int
服务端口设置参数为:-port=80
-tcp_port int
TCP服务端口描述: -tcp_port=2001 #./go_flag -port 8090 -config=/usr/local/service/config -logfile= /usr/local/service/log/service.log -tcp_port=2001
service tcp port : 2001
service port : 8090
service config : /usr/local/service/config
service logfile : /usr/local/service/log/service.log

查看帮助:

#./go_flag -h
cli : go_flag -port=8080 -config=/usr/local/service/config -logfile=/usr/local/service/log/service.log
-config string
配置文件配置参数为:-config=/usr/local/service/config
-logfile string
日志文件配置参数为:-logfile=/usr/local/service/log/service.log
-port int
服务端口设置参数为:-port=80
-tcp_port int
TCP服务端口描述: -tcp_port=2001

Flag语法:

  • -flag 只支持bool参数
  • -flag=p
  • -flag p bool类型不能使用,当p为false时会引起歧义

Flag解析:

parseOne()函数来处理-flag=value的,如果处理成功后,会将flag存储到FlagSet.actucal map[string]*Flag中。

flag.Parse()函数来解析命令行中的参数中定义的flag,该方法遇到第一个非flag的命令方法就中止。

1、non-flag的时候,会终止解析工作。

2、连续两个“-”的时候,会终止解析工作。

然后,再看我们传递错误的参数的返回情况。

#./go_flag -a=b
flag provided but not defined: -a
cli : go_flag -port=8080 -config=/usr/local/service/config -logfile=/usr/local/service/log/service.log
-config string
配置文件配置参数为:-config=/usr/local/service/config
-logfile string
日志文件配置参数为:-logfile=/usr/local/service/log/service.log
-port int
服务端口设置参数为:-port=80
-tcp_port int
TCP服务端口描述: -tcp_port=2001

跟踪到代码中可以看到如图:

从上例可见,其实flag并没有非常强大,下一章节会介绍一个更强大的命令行解析工具。

总结:

  1. os标准库提供的解析方法,能够解析简单的命令行参数。
  2. flag能够解析约定好的常规按照-flag传递的命令行参数,有帮助信息。
  3. os和flag还不能够解析复杂结构的启动参数。

喜欢的话,可以关注公众号

Go语言 命令行解析(一)的更多相关文章

  1. 【嵌入式开发】C语言 命令行参数 函数指针 gdb调试

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21551397 | http://www.hanshul ...

  2. .NET:命令行解析器介绍

    背景 经常需要开发一下小工具,之前都是自己解析命令行参数,接触过动态语言社区以后,发现命令行解析有特定的模式和框架可以利用,本文介绍一个 .NET 平台的类库. 示例 需求 拷贝文件,如:CopyFi ...

  3. C语言 命令行参数 函数指针 gdb调试

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21551397 | http://www.hanshul ...

  4. Python命令行解析argparse常用语法使用简介

    查看原文:http://www.sijitao.net/2000.html python中的命令行解析最简单最原始的方法是使用sys.argv来实现,更高级的可以使用argparse这个模块.argp ...

  5. Noah的学习笔记之Python篇:命令行解析

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

  6. python命令行解析工具argparse模块【1】

    argpaser是python中很好用的一个命令行解析模块,使用它我们可以很方便的创建用户友好型命令行程序.而且argparse会自动生成帮助信息和错误信息. 一.示例 例如下面的例子,从命令行中获取 ...

  7. python实现命令行解析的argparse的使用

    参考https://docs.python.org/3.6/library/argparse.html argparse模块使编写用户友好的命令行界面变得很容易.程序定义了它需要什么参数,argpar ...

  8. 使用命令行解析php文件

    使用命令行解析php文件,这样可以调用Log4PHP库中的一些demo,因为默认的输出使用命令行作为输出. 建一个bat文件: echo 以下是使用命令行解析php文件 C:\xampp\php\ph ...

  9. 『Argparse』命令行解析

    一.基本用法 Python标准库推荐使用的命令行解析模块argparse 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的optparse.因为argparse是 ...

随机推荐

  1. C/C++、C#、JAVA(二):基本类型和转换操作

    基本类型和转换操作 数据类型 C语言中的基本类型如下. 类型 存储大小 值范围 char 1 字节 -128 到 127 或 0 到 255 unsigned char 1 字节 0 到 255 si ...

  2. Python——项目-小游戏2-动画绘制

    实现游戏循环还有事件的监听 在上一讲中 你需要完成这样的这样的效果, 如果你还没有完成,请不要继续往下阅读!!切记切记切记.,重要的事情说三遍 我们来看一下什么是游戏循环 所谓的游戏循环很好的理解 就 ...

  3. Spring Boot 整合 Redis 和 JavaMailSender 实现邮箱注册功能

    Spring Boot 整合 Redis 和 JavaMailSender 实现邮箱注册功能 开篇 现在的网站基本都有邮件注册功能,毕竟可以通过邮件定期的给用户发送一些 垃圾邮件 精选推荐

  4. Servlet(简介,请求参数,页面跳转,生命周期,创建,配置,ServletContext,线程)

    1.Servlet简介 servlet是java servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序, 主要功能在于交互式浏览和修改数据,生成动态的web内容 服务端运行的 ...

  5. elasticsearch基础及在Python中的简单使用

    目录 一. 安装java环境与elasticsearch.kibana 二. elasticsearch.kibana的部分文件说明 三. Kibana的Dev tools中ES的简单命令 四. ES ...

  6. SpringBoot启动的时候出现log4j警告(配置文件找不到)

    SpringBoot启动的时候报如下的警告 在启动SpringBoot项目的时候,idea出现如下警告信息,也就是log4j 配置文件找不到的问题 log4j:WARN No appenders co ...

  7. CentOS7 如何安装JDK(以及卸载)

    CentOS7 如何安装JDK(以及卸载) 1. 如何安装JDK? 购买云服务器后,会提供一个公网IP和内网IP,需要使用SSH工具连接到云服务器(推荐使用SecureCRT),随后就能在命令行中操作 ...

  8. SpringBoot 整合 MyCat 实现读写分离

    MyCat一个彻底开源的,面向企业应用开发的大数据库集群.基于阿里开源的Cobar产品而研发.能满足数据库数据大量存储:提高了查询性能.文章介绍如何实现MyCat连接MySQL实现主从分离,并集成Sp ...

  9. Hive内外表的区分方法及内外部差异

    Hive内外部区分方法 查看hive元数据:进入mysql中hive元数据库,查看TBLS表,查看对应的表名和表类型: 在hive-cli界面:desc extended tablename,查看Ta ...

  10. go语言系列-从零到数据类型的基本介绍

    视频资源:b站UP主v若水若水的尚硅谷go视频 不动笔墨不读书 ,虽然我有全套视频和笔记 还是自己动点笔墨 因为在19年下半年大致学过go语言 所以这么计划:一个星期拿下基础 一个星期拿下框架 两个星 ...