2021/4/6关于获取go程序命令行参数

1.使用os获取简单命令行参数

根据文档中对os包的描述可得知,os的变量Args保存了命令行的参数(第一个是程序名称),因此我们不难写出一个“hello 用户名”的程序

//demo1
package main

import (
    "fmt"
    "os"
)

var name string

func init(){
    if len(os.Args)>1 {
        name = os.Args[1]
    } else {
        name = "world"
    }
}

func main(){
    fmt.Printf("Hello %s!\n",name)
}

但是问题来了,os.Args需要预先双方规定好如何输入,且输入都转为字符串,我们想要让程序像mysql一样接收 -u -p 这样的参数

2.使用flag解析命令行复杂参数

先看一个简单的demo,具体函数使用方法见文档

package main

import (
    "fmt"
    "flag"
)

var name string

func init(){
    flag.StringVar(&name,"name","world","please input  your name")  //[1]
}

func main(){
    flag.Parse() //[2]
    fmt.Printf("Hello %s!\n",name)
}
//执行程序 go run demo.go --name=zjb
  1. 在[1]位置,我们利用 flag.StringVar 注册了一个 flag
  2. 在[2]位置,等所有flag都注册完后,调用解析函数来解析命令行参数写入注册的flag
  3. 当我们执行--help时 ,获取到帮助信息 please input your name

阅读StringVal源码,实际是调用flagset 中的Var方法

func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
        f.Var(newStringValue(value, p), name, usage)
}

继续查找Var源头

func Var(value Value, name string, usage string) {
        CommandLine.Var(value, name, usage)
}

发现实际是调用变量CommandLine的方法

Command为何物?它是一个FlagSet,根据文档描述

CommandLine是默认的命令行flag集,用于解析os.Args

var CommandLine = NewFlagSet(os.Args[0], ExitOnError)

也就是说我们可以根据这个特性继续改造我们的程序(flagSet中有一个成员,为函数类型,用于在用户输入--help 或 参数类型错误时停止程序和抛出异常提示 )

package main

import (
    "fmt"
    "flag"
    "os"
)

var name string


func init(){
    flag.CommandLine = flag.NewFlagSet("myCommand",flag.ExitOnError)
    flag.CommandLine.Usage = func(){
        fmt.Fprintf(os.Stderr, "Usage of %s:\n", "myCommand")
        flag.PrintDefaults()
    }
    flag.StringVar(&name, "name", "world", "please input your name")
}

func main(){
    flag.Parse()
    fmt.Printf("Hello %s!\n",name)
}

再简化一下

package main

import (
    "fmt"
    "flag"
    "os"
)

var name string
var cmdLine =flag.NewFlagSet("myCommand",flag.ExitOnError)

func init(){
    cmdLine.StringVar(&name, "name", "world", "please input your name")
}

func main(){
    cmdLine.Parse( os.Args[1:] )
    fmt.Printf("Hello %s!\n",name)
}

ok,简介明了

3.拓展自定义类型

思路:利用Var方法,同时实现Value接口

package main

import (
    "fmt"
    "flag"
    "os"
)
//自定义类型
type myValue struct {
    p string
}
//实现接口的Set方法 负责解析传入的值
func (f *myValue) Set( v string ) error {
    f.p = v
    return nil
}
// 获取真正的值
func (f *myValue) String() string {
    return f.p
}
// 创建类实例指针
var name *myValue = &myValue{p:"world"}
var cmdLine =flag.NewFlagSet("myCommand",flag.ExitOnError)

func init(){
    cmdLine.Var(name, "name", "please input your name")
}

func main(){
    cmdLine.Parse( os.Args[1:] )
    fmt.Printf("Hello %s!\n",name.p)
}

本文内容及代码参考:

  1. GO核心36讲
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容