go 圣经阅读笔记之-入门
go 圣经 这本书英文名为 《The Go Programming Language》
1. 简单hello world示例
helloworld.go
package main import "fmt" func main() {
//打印 hello, 世界 fmt.Println("Hello, 世界") }
运行,正常情况下会输出“Hello, 世界”:
[root@centos src]# go run helloworld.go Hello, 世界
如果要保存编译结果(helloworld)以备将来之用。 可以用build子命令:
[root@centos src]# go build helloworld.go [root@centos src]# ll 总用量 1872 -rwxr-xr-x. 1 root root 1906945 1月 12 00:04 helloworld -rw-r--r--. 1 root root 79 1月 12 00:01 helloworld.go [root@centos src]# ./helloworld Hello, 世界
下面来看各行代码的意义:
package main:定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。
import "fmt":告诉 Go 编译器这个程序需要使用 fmt 包(的函数,或其他元素),fmt 包实现了格式化 IO(输入/输出)的函数。
func main() :是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数。
fmt.Println(...) :可以将字符串输出到控制台,并在最后自动增加换行字符 \n。 使用 fmt.Print("hello, world\n") 可以得到相同的结果。
//打印 hello, 世界:为注释,Go继承自C/C++因此注释相同,使用//单行注释或者/**/多行注释。
注意:Go语言不需要在语句或者声明的末尾添加分号, 除非一行上有多条语句
2. 命令行参数
(1)os包以跨平台的方式, 提供了一些与操作系统交互的函数和变量。程序的命令行参数可从os包的Args变量获取; os包外部使用os.Args访问该变量。
首先来看Unix里echo命令的一份实现, echo把它的命令行参数打印成一行 :
// Echo1 prints its command-line arguments. package main import ( "fmt" "os" ) func main() { var s, sep string for i := 1; i < len(os.Args); i++ { s += sep + os.Args[i] sep = " " } fmt.Println(s) }
这里声明了两个string类型变量 s, sep 会被隐式的初始化为空字符串(""),运算符 += 是赋值运算符。符号 := 是短变量声明的一部分, 这是定义一个或多个变量并根据它们的初始值为这些变量赋予适当类型的语句(i := 1,初始值为1,因此 i 为int类型)。
注意:自增语句 i++ 给 i 加1; 这和 i += 1 以及 i = i + 1 都是等价的 。这里的 i++ 是语句(C语言中是表达式),因此,j = i++ 非法, 而且++和--都只能放在变量名后面, 因此 --i 也非法,注意和C语言之间的区别。
(2)for 循环
1)for 循环的第一种形式
Go语言只有for循环这一种循环语句。 for循环有多种形式, 其中一种如下所示:
for initialization; condition; post { // zero or more statements }
for循环三个部分不需括号包围。 大括号强制要求, 左大括号必须和post语句在同一行。for循环的这三个部分每个都可以省略 ,如果连 condition 也省略了就变成一个无限循环 。可以用其他方式终止循环, 如一条 break 或 return 语
句。
// a traditional infinite loop for { // ... }
2)for 循环的第二种形式
在某种数据类型的区间( range) 上遍历, 如字符串或切片。 echo 的第二版本展示了这种形式:
// Echo2 prints its command-line arguments. package main import ( "fmt" "os" ) func main() { s, sep := "", "" for _, arg := range os.Args[1:] { s += sep + arg sep = " " } fmt.Println(s) }
每次循环迭代, range 产生一对值; 索引以及在该索引处的元素值。 这个例子不需要索引,但 range 的语法要求, 要处理元素, 必须处理索引。 一种思路是把索引赋值给一个临时变量,如 temp , 然后忽略它的值, 但Go语言不允许使用无用的局部变量( local variables) , 因为这
会导致编译错误。 Go语言中这种情况的解决方法是用 空标识符 ( blank identifier) , 即 _ ( 也就是下划线) 。空标识符可用于任何语法需要变量名但程序逻辑不需要的时候。
声明一个变量有好几种方式, 下面这些都等价:
s := "" var s string var s = "" var s string = ""
第一种形式, 是一条短变量声明, 最简洁, 但只能用在函数内部, 而不能用于包变量。
第二种形式依赖于字符串的默认初始化零值机制, 被初始化为""。
第三种形式用得很少, 除非同时声明多个变量。
第四种形式显式地标明变量的类型, 当变量类 型与初值类型相同时, 类型冗余, 但如果两者类型不同, 变量类型就必须了。 实践中一般使用前两种形式中的某个, 初始值重要的话就显式地指定变量的类型, 否则使用隐式初始化。
上面实现的echo程序 每次循环都会更新 s 如果连接涉及的数据量很大, 这种方式代价高昂。 一种简单且高效的解决方案是使用 strings 包的 Join 函数
func main() { fmt.Println(strings.Join(os.Args[1:], " ")) }
3. 查找重复的行