<>

第二章重点:

Go 的源码文件分类:

在第一章的时候已经提及到了这个关键问题:

(1)命令源码文件:
    声明自己属于 main 代码包、包含无参数声明和结果声明的 main 函数。
    命令源码文件被安装以后,GOPATH 如果只有一个工作区,那么相应的
    可执行文件会被存放当前工作区的 bin 文件夹下;如果有多个工作区,
    就会安装到 GOBIN 指向的目录下。

(2)库源码文件
    
    库源码文件就是不具备命令源码文件上述两个特征的源码文件。存在于某个代码包中的普通的源码文件。

(3)测试源码文件

    名称以 _test.go 为后缀的代码文件,并且必须包含 Test 或者 Benchmark 名称前缀的函数。

GO语言的flag包:

微课堂主要介绍了一下flag包的用法。并且付上了官方文档。所以在这里稍微列举一下用法。

flag的定义:

flag.String(), Bool(), Int() //这里这是列举了几个

然后就是两种定义的方式:

var ip = flag.Int("flagname", 1234, "help message for flagname") //ip 为指针类型,Int或者
String返回的都是指针类型

flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")//此处需要在外面手动定义flagvar

第一种方式是返回一个值,第二种方式是把变量的传进去。

通过flag.Var()绑定自定义类型,自定义类型需要实现Value接口(Receives必须为指针),如:

flag.Var(&flagVal, "name", "help message for flagname")

对于这种类型的flag,默认值为该变量类型的初始值

flag的解析

flag.Parse()

解析函数将会在碰到第一个非flag命令行参数时停止,非flag命令行参数是指不满足命令行语法的参数,如命令行参数为cmd --flag=true abc则第一个非flag命令行参数为“abc”

flag解析后的参数使用

fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)

命令行语法

-flag //只支持bool类型
-flag=x
-flag x //只支持非bool类型

注意第三种只支持非bool类型,原因就是如果文件的名字为false的话那么就会产生歧义。看例子:

package main

import (
    "flag"
    "fmt"
)

var name string
var right bool
func init() {
    flag.StringVar(&name, "name", "everyone", "The greeting object.")
    flag.BoolVar(&right, "check", false, "The right ob")
}

func main() {
    flag.Parse()
    Hello(name)
    fmt.Println(right)
}

这里采用的还是老师的例子,只多加了个bool类型。
我们编译之后生成exe

demo4.exe -check false
demo4.exe -check

对于这两种都会采用默认的bool类型true。

demo4.exe -check=false

只有这样的时候,才会采用false

定义自己的参数使用说明

第一种:

最简单就是修改Usages这个函数变量:

var Usage = func() {
    fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
    PrintDefaults()
}

我们可以看一下源码里面采用的是第一个参数的名字也就是我们的exe文件。

var Usage = func() {
    fmt.Fprintf(CommandLine.Output(), "HaoLin guid%s:\n", "wenxuwan")
    PrintDefaults()
}
这样你就可以定义输出了

郝林老师还讲了更深入的定义自己的类型。主要是更深入的定义flag包里面的一些对象实现自己的方法,具体可以看下源码。

思考题

1. 默认情况下,我们可以让命令源码文件接受哪些类型的参数值?
这个从flag包的代码包里面就可以看到,这里贴一下班里一个同学的答案

    int(int|int64|uint|uint64),
    float(float|float64)
    string,
    bool,
    duration(时间),
    var(自定义)


2. 我们可以把自定义的数据类型作为参数值的类型吗?如果可以,怎样做?

    当然是可以的:
    // Var defines a flag with the specified name and usage string. The type and
    // value of the flag are represented by the first argument, of type Value, which
    // typically holds a user-defined implementation of Value. For instance, the
    // caller could create a flag that turns a comma-separated string into a slice
    // of strings by giving the slice the methods of Value; in particular, Set would
    // decompose the comma-separated string into the slice.
    func Var(value Value, name string, usage string) {
        CommandLine.Var(value, name, usage)
    }

    type pepoInfo struct{
        name string
        age int
        homeAdress string
    }

    func (p * pepoInfo) Set(val string) error{
        peopleList := strings.Split(val, ",")
        p.name = peopleList[0]
        p.age,_ =  strconv.Atoi(peopleList[1])
        p.homeAdress = peopleList[2]
        return nil
    }   

    func (s *pepoInfo) String() string {
        infoList := strings.Split("wenxuwan,20,山东", ",")
        s.name = infoList[0]
        s.age,_ = strconv.Atoi(infoList[1])
        s.homeAdress = infoList[2]
        return "It's none of my business"
    }
    func main(){

    var people pepoInfo
    flag.Var(&people, "info", "hao ma fan")
    flag.Parse()
    //打印结果slice接收到的值
    fmt.Println(people)
    }

demo4.exe --info wenxuwan,10,shouguang

你可能感兴趣的:(<>)