Go语言入门 | 青训营笔记

492 阅读1分钟

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

语言优势

语法简单,学习周期短

Go语言在C语言的基础上弃用了许多繁琐的格式和功能相似的关键字,包括if和for的括号、while和do while以及分号等,在熟悉go的语法之后能明显体会到开发时带来的随意和惬意。

//死循环
for {
   fmt.Println("loop")
   break
}
//带索引循环
for j := 7; j < 9; j++ {
   fmt.Println(j)
}

Go语言却又很好地继承了大部分基础语法,甚至作了更好的优化,比如if条件后面必须跟花括号,这就让不同人的代码风格更加相似,代码格式也更加清晰,还有switch-case的灵活优化。

t := time.Now()
switch {  //区别于C语言只能带常量表达式
case t.Hour() < 12: 
   fmt.Println("It's before noon")
default:
   fmt.Println("It's after noon")
}

标准库丰富(高稳定,高性能,持续优化)

Go语言的标准库提供了清晰的构建模块和公共接口,包含 I/O 操作、文本处理、图像、密码学、网络和分布式应用程序等,并支持许多标准化的文件格式和编解码协议。

静态链接,单一文件运行

Go语言本地库文件默认通过静态链接调用,在编译时以编译系统内包含的共享库作为资源进行链接,在运行时不再依赖系统的共享库,从而解决了对宿主系统动态链接的共享库版本有要求而带来的问题。

编译速度快,比C++快

Go语言的编译速度是快于C++的,其原因有以下几点:

  • 使用了import的引用管理方式
  • 没有模板的编译负担
  • 1.5版本后的自举编译器优化
  • 更少的关键字

据统计,Go语言只有25个关键字,而即使是C语言也有32个关键字。

基本语法

定义变量

Go语言的变量类似python和js,却又是C这类的强类型语言。

单一变量创建

var a int = 10  // 定义类型
var b = 10      // 自动判定类型
c : = 10        // 省略var

多变量创建

var a, b, c = 10, 20, 30  // 可以各自不同类型

定义数组

a := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
b := a[5]     // 指定位置索引
c := a[6:10]  // 联系位置索引
fmt.Println(b)  // 5
fmt.Println(c)  // [6,7,8,9]

关于切片

切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型,内部结构包含地址(指向数组的指针)、大小和容量。

// slice:表示目标切片对象
// 开始位置:对应目标切片对象的索引
// 结束位置:对应目标切片的结束索引
// slice [开始位置 : 结束位置]
var a  = [3]int{1, 2, 3}
fmt.Println(a, a[1:2])  // 其他用法包括a[1:] & a[:1] & a[:](原生) & a[0:0](重置) 

创建切片

// 声明字符串切片 
// 声明一个字符串切片,切片中拥有多个字符串 
var strList []string 
// 声明整型切片 
// 声明一个整型切片,切片中拥有多个整型数值 
var numList []int

make()动态创建切片

// 其中 Type 是指切片的元素类型
// size 指的是为这个类型分配多少个元素
// cap 为预分配的元素数量,这个值设定后不影响 size,只是能提前分配空间,降低多次分配空间造成的性能问题
make( []Type, size, cap )

a := make([]int, 2)
b := make([]int, 2, 10)

fmt.Println(a, b)            // [0,0] [0,0]
fmt.Println(len(a), len(b))  // 2 2

append()为切片添加元素

append()函数需要将自身作为参数传入,使a指向新的切片,究其原因,是当切片发生扩容时整个切片的地址都将整体改变。

var a []int
a = append(a, 1)                // 追加1个元素
a = append(a, 1, 2, 3)          // 追加多个元素
a = append(a, []int{1,2,3}...)  // 追加一个切片

var a = []int{1,2,3}
a = append([]int{0}, a...)         // 在开头添加1个元素
a = append([]int{-3,-2,-1}, a...)  // 在开头添加1个切片

字典map

m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m)           // map[one:1 two:2]
fmt.Println(len(m))      // 2
fmt.Println(m["one"])    // 1
fmt.Println(m["unknow"]) // 0

range

range是go中的一种遍历方式,类似于迭代器,返回索引key和索引值value,可以遍历本质上还是for循环。
range 应用于不同数据类型时,返回 (索引, 值) 或 (键, 值),下表是对应的结构:

type1st value2nd value
stringindexs[index]
array/sliceindexs[index]
mapkeym[key]
channelelement
x := []string{"a", "b", "c"}
//忽略value,只返回key
for v := range x {
   fmt.Println(v) //prints 0, 1, 2
}  //输出:0\n 1\n 2\n

//忽略key,只返回value,用_占位,该用法最为常见
for _, v := range x {
   fmt.Println(v) //prints a, b, c
}  //输出:a\n b\n c\n

//返回key和value
for k, v := range x {
   fmt.Println(k, v)
}  //输出:0 a\n 1 b\n 2 c\n

结构体

Go语言中,结构体属性名首字母大写可以使用相关函数直接序列化和反序列化。

type People struct {
	Name string
	Age  int
}

json.Marshal()  //序列化(*自动Base64编码)
json.Unmarshal()  //反序列化

函数

Go语言中函数用func定义,可以返回多个值,一般业务场景会返回结果和执行状态。

func exists(m map[string]string, k string) (v string, ok bool) {
   v, ok = m[k]
   return v, ok
}

func main() {
   res := add(1, 2)
   fmt.Println(res) // 3

   v, ok := exists(map[string]string{"a": "A"}, "a")
   fmt.Println(v, ok) // A True
}

今日分享内容到此为止,课程相关内容并未全部展示,总的来说Go语言的设计很有趣,其本身也十分强大。