Go程序设计语言1.2 命令行参数

1.2 命令行参数


大部分程序处理输入然后产生输出,这就是关于计算的大致定义。但是程序怎样获取数据的输入呢?一些程序自己生成数据,更多的时候,输入来自一个外部源:文件、网络连接、其他程序的输出、键盘、命令行参数等。随后的一些示例将从命令行参数开始讨论这些输入。

os包提供一些函数和变量,以与平台无关的方式和操作系统打交道。命令行参数以os包中Args名字的变量供程序访问,在os包外面,使用os.Args这个名字。

变量os.Args是一个字符串slice。slice是Go中的基础概念,很快我们将讨论到它。现在只需理解它是一个动态容量的顺序数组s,可以通过s[i]来访问单个元素,通过s[m:n]来访问一段连续子区间,数组长度用len(s)表示。与大部分编程语言一样,在Go中,所有的索引使用半开区间,即包含第一个索引,不包含最后一个索引,因为这样逻辑比较简单。例如,slice s[m:n],其中,0≤m≤n≤len(s),包含n-m个元素。

os.Args的第一个元素是os.Args[0],它是命令本身的名字;另外的元素是程序开始执行时的参数。表达式s[m:n]表示一个从第m个到第n-1个元素的slice,所以下一个示例中slice需要的元素是os.Args[1:len(os.Args)]。如果m或n缺失,默认分别是0或len(s),所以我们可以将期望的slice简写为os.Args[1:]。

这里有一个UNIX echo命令的实现,它将命令行参数输出到一行。该实现导入两个包,使用由圆括号括起来的列表,而不是独立的import声明。两者都是合法的,但为了方便起见,我们使用列表的方式。导入的顺序是没有关系的,gofmt工具会将其按照字母顺序表进行排序(当一个示例有几个版本时,通常给它们编号以区分出当前讨论的版本)。

 

 

注释以//开头。所有以//开头的文本是给程序员看的注释,编译器将会忽略它们。习惯上,在一个包声明前,使用注释对其进行描述;对于main包,注释是一个或多个完整的句子,用来对这个程序进行整体概括。

var关键字声明了两个string类型的变量s和sep。变量可以在声明的时候初始化。如果变量没有明确地初始化,它将隐式地初始化为这个类型的空值。例如,对于数字初始化结果是0,对于字符串是空字符串""。在这个示例中,s和sep隐式初始化为空字符串。第2章将讨论变量和声明。

对于数字,Go提供常规的算术和逻辑操作符。当应用于字符串时,+操作符对字符串的值进行追加操作,所以表达式

 

表示将sep和os.Args[i]追加到一起。程序中使用的语句

 

是一个赋值语句,将sep和os.Args[i]追加到旧的s上面,并且重新赋给s,它等价于下面的语句:

 

操作符+=是一个赋值操作符。每一个算术和逻辑操作符(例如+或者*)都有一个对应的赋值操作符。

echo程序会循环每次输出,但是这个版本中我们通过反复追加来构建一个字符串。字符串s一开始为空字符串"",每一次循环追加一些文本。在第一次迭代后,一个空格被插入,这样当循环结束时,每个参数之间都有一个空格。这是一个二次过程,如果参数数量很大成本会比较高,不过对于echo程序还好。本章和下一章会展示几个改进版本,它们会逐步处理掉低效的地方。

循环的索引变量i在for循环开始处声明。:=符号用于短变量声明,这种语句声明一个或多个变量,并且根据初始化的值给予合适的类型,下一章会详细讨论它。

递增语句i++对i进行加1,它等价于i += 1,又等价于i = i + 1。对应的递减语句i--对i进行减1。这些是语句,而不像其他C族语言一样是表达式,所以j = i++是不合法的,并且仅支持后缀,所以--i不合法。

for是Go里面的唯一循环语句。它有几种形式,这里展示其中一种:

 

for循环的三个组成部分两边不用小括号。大括号是必需的,但左大括号必须和post(后置)语句在同一行。

可选的initialization(初始化)语句在循环开始之前执行。如果存在,它必须是一个简单的语句,比如一个简短的变量声明,一个递增或赋值语句,或者一个函数调用。condition

(条件)是一个布尔表达式,在循环的每一次迭代开始前推演,如果推演结果是真,循环则继续执行。post语句在循环体之后被执行,然后条件被再次推演。条件变成假之后循环结束。

三部分都是可以省略的。如果没有initialization和post语句,分号可以省略:

 

如果条件部分都不存在,例子如下:

 

循环是无限的,尽管这种形式的循环可以通过如break或return等语句进行终止。

另一种形式的for循环在字符串或slice数据上迭代。为了说明,这里给出第2版的echo:

 

 

每一次迭代,range产生一对值:索引和这个索引处元素的值。这个例子里,我们不需要索引,但是语法上range循环需要处理,因此也必须处理索引。一个主意是我们将索引赋予一个临时变量(如temp)然后忽略它,但是Go不允许存在无用的临时变量,不然会出现编译错误。

解决方案是使用空标识符,它的名字是_(即下划线)。空标识符可以用在任何语法需要变量名但是程序逻辑不需要的地方,例如丢弃每次迭代产生的无用的索引。大多数Go程序员喜欢搭配使用range和_来写上面的echo程序,因为索引在os.Args上面是隐式的,所以更不容易犯错。

这个版本的程序使用短的变量声明来声明和初始化s和sep,但是我们可以等价地分开声明变量。以下几种声明字符串变量的方式是等价的:

 

为什么我们更喜欢某一个?第一种形式的短变量声明更加简洁,但是通常在一个函数内部使用,不适合包级别的变量。第二种形式依赖默认初始化为空字符串的""。第三种形式很少用,除非我们声明多个变量。第四种形式是显式的变量类型,在类型一致的情况下是冗余的信息,在类型不一致的情况下是必需的。实践中,我们应当使用前两种形式,使用显式的初始化来说明初始化变量的重要性,使用隐式的初始化来表明初始化变量不重要。

如上所述,每次循环,字符串s有了新的内容。+=语句通过追加旧的字符串、空格字符和下一个参数,生成一个新的字符串,然后把新字符串赋给s。旧的内容不再需要使用,会被例行垃圾回收。

如果有大量的数据需要处理,这样的代价会比较大。一个简单和高效的方式是使用strings包中的Join函数:

 

最后,如果我们不关心格式,只是想看值,或许只是调试,那么用Println格式化结果就可以了:

 

这个输出语句和我们从strings.Join得到的输出很像,不过两边有括号。任何slice都能够以这样的方式输出。

练习1.1:修改echo程序输出os.Args[0],即命令的名字。

练习1.2:修改echo程序,输出参数的索引和值,每行一个。

练习1.3:尝试测量可能低效的程序和使用strings.Join的程序在执行时间上的差异。(1.6节有time包,11.4节展示如何撰写系统性的性能评估测试。)

时间: 2024-11-02 07:40:55

Go程序设计语言1.2 命令行参数的相关文章

c语言-C语言中的命令行参数有什么作用?

问题描述 C语言中的命令行参数有什么作用? 最近再学习C语言,在学习到命令行参数的问题的时候搞清楚了命令行参数的用法以及怎么实现的,但是目前无法理解命令行参数到底在实际编程当中的作用是是什么? 希望得到好心人的帮助,谢谢. 解决方案 你可以做一个实验.按键盘上ctrl右边的windows键,不松手,再按下r,打开运行对话框. 输入如下命令 explorer 运行,你会打开一个我的电脑的窗口,默认显示的是你的文档或者当前目录. 关闭,再输入 explorer c: 这次打开我的电脑,并且默认显示的

C语言程序设计之命令行参数

  在许多应用软件运行时都带有命令行参数,其实这些命令行参数在C语言编写的程序中也可以实现,灵活地运用命令行参数进行处理可以有效地提高程序的运行效率,收到事半功倍的效果. C语言中有关命令行参数涉及到程序的主函数main(int argc,char *argv[]这样两个参数,其中,int argc表示命令行参数的个数(包括可执行程序名本身),char *argv[]表示每个参数的具体内容,argv[0]为命令行中可执行程序名本身,argv[1]为命令行中第二个参数的内容,依次类推.如下例输出命

c语言-C语言,用命令行参数复制文件,请问哪里出错了

问题描述 C语言,用命令行参数复制文件,请问哪里出错了 #include #include int main(int argc, char *argv[]) { int ch; errno_t err; FILE *source, *destination; if ((err = fopen_s(&source, argv[1], "rb") )!=0) { printf("can't open %sn", argv[1]); exit(1); } if (

c语言-C语言使用命令行参数问题

问题描述 C语言使用命令行参数问题 在C语言中,为了使用命令行参数,main函数的第一行一般形式为void main(int argc,char*argv[]),如果命令行为"test a 3 data",则argv[0]表示的是:A)test B)a C)3 D)data===答案是A,求大侠解释? 解决方案 依次 agrv[0]代表程序名,argv[1]....之后代表参数 解决方案二: 当然了,参数用空格分隔.第一个是test.第二个是a,等等.选a 解决方案三: 学习C语言时一

php 命令行参数详解及应用

命令行|详解 大家知道,php是一种PHP是一个基于服务端来创建动态网站的脚本语言,您可以用PHP和HTML生成网站主页.当用户打开php页面时,服务端便执行PHP的命令并将执行结果发送至用户的浏览器中,这类似于ASP和CoildFusion,PHP可以运行在WINDOWS和多种版本的UNIX上.除了能够操作您的页面外,PHP还能发送HTTP的标题.您可以设置cookie,管理数字签名和重定向用户,而且它提供了极好的连通性到其它数据库(还有ODBC),集成各种外部库来做用PDF文档解析XML的任

C/C++中命令行参数的原理

很早以前的dos应用程序中,我们经常会用命令行参数执行应用程序例如: copy c:\1.txt d:\ 在c/c++中,命令行参数的传递是利用main进行形参传递实现的 前面的教程中我们对面都进行了void main()或者是void main(void)的定义,这表示main不返回任何类型,和main不带有任何参数,但在缺剩状态下mian()这样形式下,形式参数一直是存在在栈空间内的只是隐藏了起来. 为了实现命令行参数我们将使用main(int argc,char* argv[])这样的形式

在C++ Builder中取得命令行参数

用过C语言编程的人都知道,在DOS下的编程可以通过main函数的参数取得命令行参数的个数以及每个参数的字符串,例如 int main(int argv ,char *argv[]) { - } 则命令行参数是argc个,这些参数分别存储在argv[0]-argv[argc-1]中,其中argv[0]是可执行文件的名字(含路径),那么Windows程序是怎么取得命令行参数的呢?用C语言写过windows程序的人都知道,在windows程序的主函数WinMain()中,有一个参数lpszCmd,这个

如何分析命令行参数

如何分析命令行参数     GNU/Linux的命令行选项有两种类型:短选项和长选项,前者以 '-' 作为前导符,后者以 '--' 作为前导符.     比如有一个命令: $ myprog -a vv --add -b --file a.txt b.txt - -- -e c.txt     在GNU/Linux系统,对这种情况的一种合理解释是:     a是短选项,带一个参数vv:     add是长选项,无参数:     b是短选项,无参数:     file是长选项,带一个参数a.txt:

Arg_parser 1.7发布 命令行参数分析工具

Arg_parser 是一个命令行参数分析工具,遵循POSIX和GNU标准.它提供了现有的C++++和Chttp://www.aliyun.com/zixun/aggregation/18713.html">语言版本的参数分析,C++版本可以作为一个C++类,能够解析配置文件的选项:同时C语言版本实现了一个单一的结构加上相关的功能.其特点是简单易用,比'getopt_long'更安全. Arg_parser 1.7该版本主要是一些轻微错误的修正.GNU编码标准已更改为引号字符.配置选项&q