7.21 每日学习

80 阅读4分钟

go语言基础查漏补缺

前几天刷题,虽然简单题会做,但是写的方法和格式过于复杂,还是得再把go的基础过一遍,查漏补缺。 以下内容整理自Go 语言之旅 (go-zh.org)

defer

defer 语句会将函数推迟到外层函数返回之后执行。

推迟调用的函数其参数会立即求值,但直到外层函数返回前该函数都不会被调用

如下 image.png

感觉,可能会在倒序中有比较好的用途。下图所示:

	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}

会输出9 8 xxx

指针

Go 也拥有指针。指针保存了值的内存地址

类型 *T 是指向 T 类型值的指针。其零值为nil。

var p *int & 操作符会生成一个指向其操作数的指针。

i := 42 p = &i

*操作符表示指针指向的底层值。

fmt.Println(*p) // 通过指针 p 读取 i

*p = 21 // 通过指针 p 设置 i

这也就是通常所说的“间接引用”或“重定向”。

但与 C 不同的点在于,Go 没有指针运算

结构体

7.19日的每日一题就碰见了构建结构体的方法。(将索引和值都放在一个结构体中存储)

func main() {
	v := Vertex{1, 2}
	v.X = 4
	fmt.Println(v.X)
}

访问是通过 . 来进行,和c语言一样。

数组

类型 [n]T 表示拥有 n 个 T 类型的值的数组。

表达式

var a [10]int

会将变量 a 声明为拥有 10 个整数的数组。

数组的长度是其类型的一部分,因此数组不能改变大小。这看起来是个限制,不过没关系,Go 提供了更加便利的方式来使用数组。

直接声明是无法改变大小的,前面刷leetcode就踩坑了。

用 make 创建切片

切片可以用内建函数 make 来创建,这也是你创建动态数组的方式。

make 函数会分配一个元素为零值的数组并返回一个引用了它的切片:

a := make([]int, 5)  // len(a)=5
要指定它的容量,需向 make 传入第三个参数:

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:]      // len(b)=4, cap(b)=4

向切片追加元素 使用append函数

append 的第一个参数 s 是一个元素类型为 T 的切片,其余类型为 T 的值将会追加到该切片的末尾。

append 的结果是一个包含原切片所有元素加上新添加元素的切片。

当 s 的底层数组太小,不足以容纳所有给定的值时,它就会分配一个更大的数组。返回的切片会指向这个新分配的数组。

举例:

func main() {
	var s []int
	printSlice(s)

	// 添加一个空切片
	s = append(s, 0)
	printSlice(s)

	// 这个切片会按需增长
	s = append(s, 1)
	printSlice(s)

	// 可以一次性添加多个元素
	s = append(s, 2, 3, 4)
	printSlice(s)
}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

输出

len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=5 cap=6 [0 1 2 3 4]

注:cap作用

切片是可索引的,并且可以由 len () 方法获取长度。 切片提供了计算容量的方法 cap () 可以测量切片最长可以达到多少。

循环

我刷题用的一般都是最普通的for循环,然后 依次初始化,判断条件,条件满足后的操作 三部。

但是也可以用range来遍历

当使用 for 循环遍历切片时,每次迭代都会返回两个值。第一个值为当前元素的下标,第二个值为该下标所对应元素的一份副本。

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
	for i, v := range pow {
		fmt.Printf("2**%d = %d\n", i, v)
	}
}

输出

2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128

也可以值赋予 _ 来忽略它。

for i, _ := range pow

for _, value := range pow

若你只需要索引,忽略第二个变量即可。

for i := range pow

如例题:

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)
	}
}

输出

1
2
4
8
16
32
64
128
256
512