上一篇文章讲述了go的起步,也就是go的一些命令和go项目组织方式,这篇开始正式学习一下Go的语法。
变量
如果你也像我一样之前学的是C/C++/Java的话,可能就会觉得Go语言既熟悉又陌生。他的很多关键词其实来自于老牌语言,但也有自己很独特的地方。 Go里面声明一个变量,最简单的就是
var name type //声明一个type类型的变量名为name的变量
//例如
var name string
var age int
注意类型在后面,变量名在前面,这一点一定要适应好,因为在传统语言里我们都习惯了int a这种类型在前的写法了。 当然也可以声明变量时同时初始化:
var age int = 3
如果你打过算法竞赛,你就知道在C++里面变量忘记初始化很多时候会成为一个问题,一个在函数内的变量未初始化,它的值很可能是不确定的,而在Go里面,一个变量总有默认的值,如int类型就是0等等。
go还支持一种类似于Python的短命名(只能在函数内使用)
age := 3
Go还有一个特点,那就是在函数一个变量被声明就必须使用————这是在语法层面上的,不用你就编译不起来。其他语言虽然也建议这么做,但没有做的这么强制的,这使得你的代码里不会再有那些忘记用的随手开的无用变量,很特别。
常量
常量和变量没有太大区别,只是加const关键词而已,和C++的一样。
const PI float32 = 3.14
一个特殊关键字iota,一个只能被系统修改的量,初始为0,每次被调用值+1, 遇到const修改为0.
数据类型
Go里面的数据类型和其他语言大同小异,不再赘述。 获取一个变量的类型可以用:
fmt.Printf("%T", x)
字符串
字符串连接,四种方式 1:加号链接 2:Sprintf格式化 3.String.Join函数 4.写入Buffer缓冲区(效率高)
格式化输出
1.数字的不同格式(二进制,十六进制) 2.指针地址输出 3.布尔类型输出 4.结构体不同信息量输出
数组
1.定义数组,没有初始值(默认是0)
func test1() {
var a1 [2]int
fmt.Printf("a1:%T\n", a1)
fmt.Printf("a1:%v\n", a1)
}
2.定义数组并列表初始化
func test2() {
var a1 = [2]int{2, 5}
fmt.Printf("a1:%T\n", a1)
fmt.Printf("a1:%v\n", a1)
}
3.自动推断数组大小
func test3() {
var a1 = [...]int{1, 2, 3}
fmt.Printf("a1:%T\n", a1)
fmt.Printf("a1:%v\n", a1)
}
4.列表初始化默认是从前往后顺序填充,下面是按照索引填充:
func test4() {
var a1 = [3]int{0: 5, 2: 3}
fmt.Printf("a1:%T\n", a1)
fmt.Printf("a1:%v\n", a1)
}
- 学C++的都知道C++11之后引入了基于范围的for循环,C++17之后引入了基于结构体的循环 go里面也有类似的操作,如下:
func test5() {
var a1 = [3]int{0: 5, 2: 3}
for i, v := range a1 {
fmt.Printf("%v %v\n", i, v)
}
}
数组切片
- 创建空切片
var a1 []int
fmt.Printf("%v\n", a1)
2.指定长度(默认元素为0)
var a2 = make([]int, 5)
fmt.Printf("%v\n", a2)
3.指定长度和容量(元素个数达到容量时会自动扩容为两倍,若不指定容量初始默认为长度两倍)
var a3 = make([]int, 3, 5)
fmt.Printf("%v\n", a3)
fmt.Printf("%v\n", len(a3))
fmt.Printf("%v\n", cap(a2))
4.使用数组初始化切片
var a1 = [...]int{1, 2, 3, 4, 5}
s1 := a1[0:3]
fmt.Printf("%v\n", s1)
5.直接初始化
var a1 = []int{1, 2, 3, 4, 5}
唯一的区别只在于【】中没有...推断长度。
6.切片遍历 切片的遍历方式和数组相似,都是两种,一种是直接通过下标循环遍历,一种是使用for range遍历。
7.加入、删除元素 GO语言没有专门的删除函数,使用的是拼接切片的方式:
- 切片 = 另一个切片,实际上是引用的传递,比如s1 = s2, 修改s1会导致s2也改变(用C++表达就是s1 = &s2)