程序一:输出其命令行参数
//echo 输出其命令行参数
package main
import (
"fmt"
"os"
"strings"
)
func echo1(){
var s,sep string
for i:=1;i<len(os.Args);i++{
s+=sep+os.Args[i]
sep = " "
}
fmt.Println(s)
}
func echo2(){
s,sep := "",""
for _,arg := range os.Args[1:]{
s += sep + arg
sep = " "
}
fmt.Println(s)
}
func echo3(){
fmt.Println(strings.Join(os.Args[1:]," "))
}
1.Go字符串连接
对于字符串的连接大致有两种方式:
1、通过+号连接func StrPlus1(a []string) string { var s, sep string for i := 0; i < len(a); i++ { s += sep + a[i] sep = " " } return s }
2、通过strings.Join连接
func StrPlus2(a []string) string { return strings.Join(a, " ") }
对比两种方式的效率,通过压力测试进行对比
import "testing" func BenchmarkStrPlus1(b *testing.B) { for i := 0; i < b.N; i++ { StrPlus1([]string{"xxx", "bbb", "aaa"}) } } func BenchmarkStrPlus2(b *testing.B) { for i := 0; i < b.N; i++ { StrPlus2([]string{"xxx", "bbb", "aaa"}) } }
运行压力测试go test -test.bench=".*"
goos: darwin goarch: amd64 BenchmarkStrPlus1-4 10000000 127 ns/op BenchmarkStrPlus2-4 20000000 78.7 ns/op
从本机来看通过+号连接字符串每个操作消耗127ns时间,strings.Join消耗78.7ns。效率上strings.Join更高
来看下strings包中Join的实现
// Join concatenates the elements of a to create a single string. The separator string // sep is placed between elements in the resulting string. func Join(a []string, sep string) string { switch len(a) { case 0: return "" case 1: return a[0] case 2: // Special case for common small values. // Remove if golang.org/issue/6714 is fixed return a[0] + sep + a[1] case 3: // Special case for common small values. // Remove if golang.org/issue/6714 is fixed return a[0] + sep + a[1] + sep + a[2] } //n为计算sep与命令行参数总共所需字节数 n := len(sep) * (len(a) - 1) for i := 0; i < len(a); i++ { n += len(a[i]) } b := make([]byte, n) bp := copy(b, a[0]) for _, s := range a[1:] { bp += copy(b[bp:], sep) bp += copy(b[bp:], s) } return string(b) }
可以看出当连接字符串数量较大时,是先通过make分配足够的空间,然后把每个字符串copy到空间里面,而不是每次通过+号来多次分配内存。
2.命令行参数
1. os.args
func main () { for idx, args := range os.Args { fmt.Println("参数",idx,":",args) } }
运行结果如下:
os.Args是一个存储命令行参数的字符串切片,它的第一个元素是执行文件的名称。
2. flag包
flag包支持的命令行参数类型有bool、int、int64、uint、uint64、float float64、string、duration。
flag参数 有效值 字符串flag 合法字符串 整数flag 1234、0664、0x1234等类型,也可以是负数。 浮点数flag 合法浮点数 bool类型flag 1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False。 时间段flag 任何合法的时间段字符串。如”300ms”、”-1.5h”、”2h45m”。 合法的单位有”ns”、”us” /“µs”、”ms”、”s”、”m”、”h”。
1. flag.Type(flag名, 默认值, 帮助信息)*Type
func main() { // 第一个参数是命令行key,第二个参数是默认是,第三个参数是 .exe -h 提示 var user = flag.String("user", "root", "用户名") var port = flag.Int("port", 3306, "端口") var ip = flag.String("ip", "localhost", "mysql ip") //必须使用flag.Parse()解析一下命令行参数 flag.Parse() //flag.Type返回的是一个指针,必须通过 *变量取值 fmt.Println(*user,*port,*ip) }
2. flag.TypeVar(Type指针, flag名, 默认值, 帮助信息)
flag.Type
返回的是指针。需要用*变量
才能取到值。var name string var age int var married bool var delay time.Duration flag.StringVar(&name, "name", "张三", "姓名") flag.IntVar(&age, "age", 18, "年龄") flag.BoolVar(&married, "married", false, "婚否") flag.DurationVar(&delay, "d", 0, "时间间隔")
通过以上两种方法定义好命令行flag参数后,需要通过调用
flag.Parse()
来对命令行参数进行解析。支持的命令行参数格式有以下几种:
- -flag xxx (使用空格,一个-符号)
- –flag xxx (使用空格,两个-符号)
- -flag=xxx (使用等号,一个-符号)
- –flag=xxx (使用等号,两个-符号)
其中,布尔类型的参数必须使用等号的方式指定。
Flag解析在第一个非flag参数(单个”-“不是flag参数)之前停止,或者在终止符”–“之后停止。
3.其他函数
- flag.Args() 返回命令行参数后的其他参数,以[]string类型
- flag.NArg() //返回命令行参数后的其他参数个数
- flag.NFlag() //返回使用的命令行参数个数
func main() { //定义命令行参数方式1 var name string var age int var married bool var delay time.Duration flag.StringVar(&name, "name", "张三", "姓名") flag.IntVar(&age, "age", 18, "年龄") flag.BoolVar(&married, "married", false, "婚否") flag.DurationVar(&delay, "d", 0, "延迟的时间间隔") //解析命令行参数 flag.Parse() fmt.Println(name, age, married, delay) //返回命令行参数后的其他参数 fmt.Println(flag.Args()) //返回命令行参数后的其他参数个数 fmt.Println(flag.NArg()) //返回使用的命令行参数个数 fmt.Println(flag.NFlag()) }
命令行参数使用提示:
$ ./flag_demo -help Usage of ./flag_demo: -age int 年龄 (default 18) -d duration 时间间隔 -married 婚否 -name string 姓名 (default "张三")
正常使用命令行flag参数:
$ ./flag_demo -name pprof --age 28 -married=false -d=1h30m pprof 28 false 1h30m0s [] 0 4
使用非flag命令行参数:
$ ./flag_demo a b c 张三 18 false 0s [a b c] 3 0
:
$ ./flag_demo -name pprof --age 28 -married=false -d=1h30m pprof 28 false 1h30m0s [] 0 4
使用非flag命令行参数:
$ ./flag_demo a b c 张三 18 false 0s [a b c] 3 0