学习总结
go语言
1
2
3
Go是一门编译型语言,Go语言的工具链将源代码及其依赖转换成计算机的机器指令(译注:静态编译)
Go语言原生支持Unicode,它可以处理全世界任何语言的文本
程序基本构造
1
2
3
4
5
6
7
8
1. package 声明语句, 表示该文件属于哪个包
2. import声明必须跟在文件的package声明之后
3. 之后则是组成程序的函数、变量、常量、类型的声明语句(分别由关键字func、var、const、type定义)
特别注意:
Go语言不需要在语句或者声明的末尾添加分号,除非一行上有多条语句
go的编译器会主动把特定符号后的 换行符 转换为 分号
go 语言格式化工具
1
2
gofmt: 把代码格式化为标准格式,按照字母顺序对包名排序
goimports: 可以根据代码需要,自动地添加或删除import声明
注释
1
注释语句以//开头
声明变量
1
2
3
变量会在声明时直接初始化。如果变量没有显式初始化,则被隐式地赋予其类型的零值(zero value),数值类型是0,字符串类型是空字符串""
var s, sep string //var声明定义了两个string类型的变量s和sep
字符串的切片
1
2
3
4
5
和大多数编程语言类似,区间索引时,Go言里也采用左闭右开形式,即,区间包括第一个索引元素,不包括最后一个
比如a = [1, 2, 3, 4, 5], a[0:3] = [1, 2, 3]
连接字符串:
s += sep + os.Args[i] ==> s = s + sep + os.Args[i]
for 循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Go语言只有for循环这一种循环语句
1. 一般格式
for initialization; condition; post {
// zero or more statements
}
for循环三个部分不需括号包围
initialization: 语句是可选的,在循环开始前执行
initalization如果存在,必须是一条简单语句
短变量声明
自增语句
赋值语句
函数调用
condition: 是一个布尔表达式
post: 语句在循环体执行结束后执行,之后再次对condition求值
2. 特别使用,省略条件
for循环的这三个部分每个都可以省略,如果省略initialization和post,分号也可以省略:
// a traditional "while" loop
for condition {
// ...
}
如果连condition也省略了,像下面这样:
for {
// ...
}
这就变成一个无限循环,尽管如此,还可以用其他方式终止循环,如一条break或return语句
注意:
Go语言不允许使用无用的局部变量(local variables),因为这会导致编译错误
声明一个变量有好几种方式,下面这些都等价:
s := "" 是一条短变量声明,最简洁,但只能用在函数内部,而不能用于包变量
var s string 依赖于字符串的默认初始化零值机制,被初始化为""
var s = "" 用得很少,除非同时声明多个变量
var s string = "" 显式地标明变量的类型,当变量类型与初值类型相同时,类型冗余,但如果两者类型不同,变量类型就必须了
一般使用前两种形式中的某个,初始值重要的话就显式地指定变量的类型,否则使用隐式初始化
if 语句
1
2
3
4
5
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
if语句条件两边不加括号,但是主体部分需要加。if语句的else部分是可选的,在if的条件为false时执行
输入源
1
2
3
4
5
6
7
8
9
10
11
1. os.Args变量是一个字符串(string)的切片(slice)
os.Args[0],是命令本身的名字;
其它的元素则是程序启动时传给它的参数
如果省略切片表达式的m或n,会默认传入0或len(s),因此
os.Args[1:len(os.Args)] = os.Args[1:]
2. os.Open打开各个具名文件
f, err := os.Open(filename)
3. io/ioutil包: ReadFile函数
data, err := ioutil.ReadFile(filename)
输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
fmt.Println("输出内容")
fmt: 包名;
Println: 基础函数
fmt.Printf("%d\t%s\n", n, line)
Printf有一大堆这种转换, 下面的表格虽然远不是完整的规范,但展示了可用的很多特性:
%d 十进制整数
%x, %o, %b 十六进制,八进制,二进制整数。
%f, %g, %e 浮点数: 3.141593 3.141592653589793 3.141593e+00
%t 布尔:true或false
%c 字符(rune) (Unicode码点)
%s 字符串
%q 带双引号的字符串"abc"或带单引号的字符'c'
%v 变量的自然形式(natural format)
%T 变量的类型
%% 字面上的百分号标志(无操作数)
Printf: 不会换行
Println: 最后添加一个换行符
按照惯例,(后缀f指format,ln指line)
以 f 结尾的格式化函数,
如log.Printf和fmt.Errorf,都采用fmt.Printf的格式化准则
以 ln 结尾的格式化函数,则遵循Println的方式,以跟%v差不多的方式格式化参数,并在最后添加一个换行符。
map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Go中的map是一个指针,它的底层是数组,而且用到了两个数组,其中一个更底层的数组用于打包保存key和value。将key经过hash函数处理,然后映射到value,实现一一对应的关系
map存储了键/值(key/value)的集合,对集合元素,提供常数时间的存、取或测试操作
键: 可以是任意类型,只要其值能用==运算符比较
最常见的例子是字符串;
值: 可以是任意类型
内置函数make创建空map: my_map := make(map[string]int)
类似于Java语言中的HashMap,Python语言中的dict,Lua语言中的table,通常使用hash实现
在向map中存储元素的时候,会将每个key经过hash运算,根据运算得到的hash值选择合适的hash bucket(hash桶),让后将各个key/value存放到选定的hash bucket中。如果一来,整个map将根据bucket被细分成很多类别,每个key可能会交叉地存放到不同的bucket中。
注意:
map中的元素是无序的,遍历时的顺序是随机的,即使两次以完全相同的顺序存放完全相同的元素,也无法保证遍历时的顺序
bufio 包
1
2
3
4
5
6
7
8
9
10
11
处理输入和输出
Scanner类型是该包最有用的特性之一
它读取输入并将其拆成行或单词;
通常是处理行形式的输入最简单的方法
input := bufio.NewScanner(os.Stdin)
> 该变量从程序的标准输入中读取内容
> 每次调用input.Scan(),即读入下一行,并移除行末的换行符
> 读取的内容可以调用input.Text()得到
> Scan函数在读到一行时返回true,不再有输入时返回false
本文由作者按照
CC BY 4.0
进行授权