Go语言基础 | 青训营笔记

63 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第1天

本堂课重点内容

  • Go语言背景知识
  • Go基础语法

详细知识点介绍

Go语言背景知识

  • Go语言具有高并发、语法简单、工具链完善、标准库丰富等优点。
  • 字节由于早期团队非Java背景且Python具有性能问题选择了Go。

Go基础语法

由于我之前接触过Go语言,这里挑几个重点的讲。

变量

可以通过var加类型的方式定义变量:var a int, 也可以让编译器帮你类型推断:a:=3

条件分支(if-else)

条件不需要用括号包裹,但是语句块必须用大括号包裹。

循环

跟C相比,Go语言只有for循环,且for语句不需要加括号,但循环体必须加大括号。但for内部的三个部分与C是一样的,且可以在第一部分定义局部变量。

for n:=0; n<5; n++ {
    fmt.Println(n)
}

switch

Go的switch执行完一个语句块后,默认不接着执行下一个,而是直接跳出,否则需要在语句块最后加fallthrough

变量类型

Go里的变量主要分值类型和引用类型两种。值类型直接存储值,例如各种数字(int等)、字符串、数组、结构体等。引用类型类似指针,其对应的地址里存的是真正的数据,如指针、slice、channel、map等。

引用类型作为参数时,传入函数的是其地址,在函数内部对其的修改会影响原来的参数。 值类型可以用make初始化,它与new的区别是,不仅分配了一块内存,还将其初始化。

错误处理

在会发生异常的函数里,可以返回函数值和error类型两个参数。然后就是Go语言特色

val, err := f()
if err != nil {
    //错误处理
}

实践练习例子

关于引用类型slice的一个例子。slice在达到容量之后会进行扩容,而扩容之后的那个slice就不是原来的silice了。

package main

import "fmt"

func f(x []int) {
   //x = append(x, 4)
   x[0] = 666
   fmt.Println(x, cap(x))
}
func main() {
   a := make([]int, 0)
   a = append(a, 1)
   a = append(a, 2)
   f(a)
   fmt.Println(a, cap(a))
}

若注释掉x = append(x, 4),以上代码的执行结果是:

[666 2] 2
[666 2] 2

若不注释,结果是:

[666 2 4] 4
[1 2] 2

这是因为在执行f函数前,a的容量和长度都是2,是满的。开始执行f时,由于slice是引用类型,参数x和a都是一样的,指向同一块内存。 若直接对x[0]进行修改,则a也一样会变。

但倘若往x中追加元素,由于x已满,会触发扩容,新产生一个容量为4(原容量翻倍)的slice赋值给x,此时x和a就不一样了。因此接下来对x的修改不会反映在a上。

避免这个问题的最简单办法是,一开始就给slice初始化足够的容量,确保其不会扩容。

课后个人总结

个人感觉,Go基础知识中需要注意的就是那几个引用类型,最好花点时间了解一下其实现原理。有时间的话再多看看Go的标准库的实现。