1.2 Go 本地化
1.3 Go 离线版
1.4 Go 练习场
2.1 包——每个Go程序都是由包构成的。
2.2 导入
2.3 导出名
2.4 函数
2.5函数(续)——当连续两个或多个函数的已命名形参类型相同时,除最后一个类型以外,其它都可以省略。
2.6 多值返回
2.7命名返回值——Go的返回值被命名,它们被视作定义在函数顶部的变量。返回值的名称应当有一定的意义,它可以作为文档使用。直接返回语句应当仅用在短函数中,在长函数中它们会影响代码的可读性。
2.8变量——var 语句用于声明一个变量列表,跟函数的参数列表一样,类型在最后。
2.9变量的初始化——如果初始化值已存在,可以省略类型。
2.10 短变量声明——:=结构不能在函数外使用。
2.11基本类型
- bool
- string
- int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr - byte //uint8的别名
- rune //int32的别名
//表示一个Unicode码点 - float32 float64
- complex64 complex128//复数
零值是:
- 数值类型为0
- 布尔类型为false
- 字符串为“”(空字符串)
2.14类型推导——在声明一个变量而不指定其类型时(即使用不带类型的:=语法或var=表达式),变量的类型由右值推导得出。
2.15常量 ——常量声明与变量类似,只不过是使用const 关键字。
2.16数值常量——数值常量是高精度的值。
3.0 for——Go只有一种循环结构:for循环
基本的for循环由三部分组成,它们用分号隔开:
- 初始化语句:在第一次迭代前执行 通常为一句短变量声明,该变量声明仅在for语句的作用域中可见。
- 条件表达式:在每次迭代前求值 一旦表达式的布尔值为false 循环迭代就会终止。
- 后置语句:在每次迭代的结尾执行
3.2for是Go中的“while”——此时你可以去掉分号。
func main() {
sum := 1
for sum < 1000 {
sum += sum
}
fmt.Println(sum)
}
3.3 无限循环
3.4 if
3.5 if的简短语句
3.6if和else
3.7switch ——是编写一连串if-else 语句的简便方法。自动提供所需的break语句,除非以fallthrough语句结束否则分支自动终止。case 对应的表达式 取值 不必为整数。
3.8switch的求值顺序。从上到下直到匹配成功时停止。
3.9 没有条件的switch 同switch true一样
3.10 defer ——会将函数推迟到外层函数放回之后执行。其被推迟的函数参数会立即求值。
3.11 defer栈——推迟的函数调用会被压入一个栈中。当外侧函数返回时,被推迟的函数会按照后进先出的顺序调用。
4.0 指针——Go拥有指针。指针保存了值得内存地址。类型*T是指向T类型值得指针。其零值为nil。&操作符会生产一个指向其操作数的指针。*操作符表示指针指向的底层值
func main() {
i, j := 42, 2701
p := &i // point to i
fmt.Println(*p) // read i through the pointer
*p = 21 // set i through the pointer
fmt.Println(i) // see the new value of i
p = &j // point to j
*p = *p / 37 // divide j through the pointer
fmt.Println(j) // see the new value of j
}
4.1 结构体——一个结构体就是一个字段的集合。
type Vertex struct {
X int
Y int
}
4.2 结构体字段
4.3 结构体指针——可以使用隐式间接引用*(p).X 写成p.X就可以。
4.4 结构体文法——结构体文法通过值接列出字段值来新分配一个结构体。
4.5 数组——类型[n]T表示拥有n 个T类型的值的数组。数组长度是其类型的一部分,因此数组不能改变大小。
4.6 切片——每个数组的大小都是固定的。而切片则为数组元素提供动态大小的、灵活的视角。在实践中,切片比数组更常用。
类型 [] T 表示一个元素类型为T的切片。
切片通过两个下标来界定,即一个上界和一个下界,二者以冒号分隔:a[low:high]
func main() {
primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[1:4]
fmt.Println(s)
}
4.7 切片就像数组的引用——切片并不存储任何数据,它只是描述底层数组中的一段。更改切片的元素会修改其底层数组中对应的元素。与它共享底层数组的切片都会观测到这些修改。
4.8 切片文法——切片文法类似于没有长度的数组文法。
[3]bool{true, true, false}
[]bool{true, true, false} 会创建一个和上面相同的数组,然后构建一个引用了它的切片。
func main() {q := []int{2, 3, 5, 7, 11, 13}
fmt.Println(q)
r := []bool{true, false, true, true, false, true}
fmt.Println(r)
s := []struct {
i int
b bool
}{
{2, true},
{3, false},
{5, true},
{7, true},
{11, false},
{13, true},
}
fmt.Println(s)
}
4.9 切片的默认行为——切片下界的默认值为0,上界则是该切片的长度。
4.10 切片的长度和容量——切片的长度和容量可通过表达式len(s)和cap(s)来获取。
4.11 nil 切片——切片的零值是nil。nil切片的长度和容量为0且没有底层数组。
4.12 用make创建切片——make函数会分配一个元素为零值得数组并返回一个引用了它的切片。
a := make([]int, 5) // len(a)=5 b := make([]int, 0, 5) // len(b)=0, cap(b)=5
4.13 切片的切片——切片可以包含任何类型,甚至包括其它切片。
func main() {
// Create a tic-tac-toe board.
board := [][]string{
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
}
// The players take turns.
board[0][0] = "X"
board[2][2] = "O"
board[1][2] = "X"
board[1][0] = "O"
board[0][2] = "X"
for i := 0; i < len(board); i++ {
fmt.Printf("%s\n", strings.Join(board[i], " "))
}
}
4.13 向切片追加元素——使用内建函数append.
func append(s []T, vs ...T) []T4.14 for循环的range 形式可以变了 切片 或 映射 。每次遍历都会返回两个值。第一个为当前元素下标,第二个为该下标对应元素的一份 副本 。
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
}
4.15 range(续) ——可以将下标或值赋予_ 来忽略它。若你只需要索引,去掉value的部分即可。
func main() {
pow := make([]int, 10)
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}
4.16 映射——映射将键映射到值,零值为nil,nil的映射即没有键,也不能添加键。make函数会返回给定类型的映射,并将其初始化备用。
type Vertex struct {
Lat, Long float64
}
var m map[string]Vertex
func main() {
m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}
fmt.Println(m["Bell Labs"])
}
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": Vertex{
40.68433, -74.39967 ,
},
"Google": Vertex{
37.42202, -122.08408 ,
},
}
简写形式如下
var m = map[string]Vertex{
"Bell Labs": {40.68433, -74.39967},
"Google": {37.42202, -122.08408},
}
4.18 修改映射
- 插入或修改
m[key]=elem - 获取元素
elem =m[key] - 删除元素
delete(m,key) - 通过双向赋值检测某个键是否存在
elem,ok:=m[key]//key在m 中 ok为true,否则 ok 为false。 elem则为元素类型的零值。
func compute(fn func(float64, float64) float64) float64 {
return fn(3, 4)
}
func main() {
hypot := func(x, y float64) float64 {
return math.Sqrt(x*x + y*y)
}
fmt.Println(hypot(5, 12))
fmt.Println(compute(hypot))
fmt.Println(compute(math.Pow))
}
4.20 函数闭包——闭包是一个函数值,它引用了其函数体之外的变量。该函数可以访问并赋予其引用的变量的值,换句话说,该函数被绑定在这些变量上。
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
func main() {
pos, neg := adder(), adder()
for i := 0; i < 10; i++ {
fmt.Println(pos(i),neg(-2*i),)
}
}