这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
01 Go语言特性
- 高性能、高并发
- 内置高并发,不需要第三方库
- 丰富的标准库、完善的工具链
- 标准库有很高的稳定性,还能享受版本迭代带来的性能优化
- 代码格式化、包管理、单元测试框架等
- 静态链接、快速编译
- 线上容器环境下编译可以将镜像体积控制的很小
- 不需要附加任何东西就可以部署运行(比如
Java的JRE) - 编译远大于
C/C++
- 跨平台
- 无需配置交叉编译环境
- 垃圾回收
- 无需考虑内存的分配释放,专注于业务逻辑
02 入门
2.1 Hello World
package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}
package是 Go 语言声明包的关键字,main是要声明的包名。main包是一个特殊的包,代表你的 Go 语言项目是一个可运行的应用程序,而不是一个被其他项目引用的库main函数是一个特殊的函数,它代表整个程序的入口,也就是程序在运行的时候,会先调用main函数,然后通过main函数再调用其他函数,达到实现项目业务需求的目的。
$ go run ch01/main.go
hello world
$ go build ch01/main.go
$ ./main
hello world
go 是一个 Go 语言开发工具包提供的命令,它和你平时常用的ls 命令一样都是可执行的命令。它可以帮助你运行 Go 语言代码,并进行编译,生成可执行的二进制文件等run 在这里是go 命令的子命令,表示要运行 Go 语言代码的意思
2.2 变量
- 字符串是内置类型,可以直接通过加号拼接,也能够直接用等于号去比较两个字符串。
var a = "initial"
g := a + "foo"
fmt.Println(g) // initialfoo
- 常量的话就是把
var改成const,值在一提的是go语言里面的常量,它没有确定的类型,会根据使用的上下文来自动确定类型
const s string = "constant"
const h = 500000000
const i = 3e20 / h
fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}
2.3 判断
需要注意三点:
- 上一个大括号的末尾必须跟下一个判断子结构
- 判断条件没有小括号
if的后面必须接大括号,不能像Java一样不加括号单独成行
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
2.4 循环
- 只有最简单的for循环,但依然可以实现多种功能
for——for init; condition; post { }while——for condition { }
- 有
continue和break两种关键字
2.5 Switch
- 与
C不同的是- 不需要加
break,是自动跳出 - 可以使用任意变量类型,不限于常量,可以更加清晰的取代多层级的判断语句
- 不需要加
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
2.6 数组
- 在
go中数组的传递为值传递,假如要在不同的方法中修改同一个数组,要使用指针作为形参 var 变量名 [N]数据类型
2.7 切片
- 业务中更加常使用切片(可变长度的数组)
- 使用
make创建切片var 变量名 []数据类型 = make([]数据类型, 长度,[容量]【可选】)- 切片的长度是它所包含的元素个数。
- 切片的容量是从它的第一个元素到其底层数组元素末尾的个数。
- 切片是数组的一个引用,其切片是引用类型
- 深拷贝传递。
- 使用append方法添加元素
切片名 = append(切片名, 添加的东西)
- 类似于
Python数组的范围取数 - 切片没有删除元素的函数,要使用拼接巧妙删除
2.8 Map(字典)
- 工程上最常用的数据类型
Map变量 := make(map[KEY类型]V类型)delect(Map变量, 对应KEY名)r, ok := m["unknow"]ok返回布尔值,以判断对应的key是否存在
- 完全无序,遍历的时候随机
2.9 range遍历
- 遍历数组第一个值是index,第二个值是value
- 遍历
map第一个值是key,第二个值是value - 不需要哪个可以通过
_关键字代替for _, value := range 遍历的数组或map
- 只想要第一个值可以不打出第二个值,不需要
_代替
2.10 函数
- 与其他语言不一样,变量类型是后置的
- 支持返回多个值
- 支持返回的值命名
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
2.11 指针
- 和
C相比功能有限,最常用的功能是对参数的修改 *对一个变量进行解引用,使用&获取一个变量的指针(引用)
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2ptr(&n)
fmt.Println(n) // 7
}
2.12 结构体
Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。- 结构体是一种自定义的类型,可以用来把相关的数据分组在一起。它由不同的字段组成,每个字段都有一个名字和一种类型。
- 结构体也能作为参数,也有非指针和指针两种用法
- 在
Go里面可以为结构体去定义一些方法。会有一点类似其他语言里面的类成员函数。 - 首字母大写是公开字段
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048")) // true
}
2.13 错误处理
Go语言中的错误处理是一种重要概念,用于处理函数或方法可能遇到的错误并作出恰当的响应。
1、Go语言中常用的错误处理方法
- 错误类型:
Go语言错误处理可以通过使用内置错误类型error进行。error类型是一个预定义的接口类型,它实现了Error()方法,表示提供有关错误信息的信息。 - 设置错误信息:在
Go语言中,我们也可以使用errors.New()函数,来设置错误信息,即自己定义的错误信息。 - 抛出错误:如果函数发生错误,则可以使用
panic()函数抛出异常,从而中断当前函数/方法的执行。
2、自定义错误处理
我们可以使用Go语言中的自定义错误处理函数,以便处理函数可能遇到的错误。自定义的错误处理函数可以检查函数的返回值,然后决定是否继续执行或者抛出错误。
3、内置recover函数
Go语言中的内置函数recover可以让我们捕获Panic异常,并执行必要的清理动作,然后终止Panic异常的流程。
2.14 字符串操作
contains:判断一个字符串里面是否有包含另一个字符串count:字符串计数index:查找某个字符串的位置join:连接多个字符串repeat:重复多个字符串replace:替换字符串
2.15 JSON处理
go语言json处理包括好几种不同的方法。最常用的应该是“encoding/json”包。它提供了Marshal()和Unmarshal()两个函数。Marshal()将struct转换为json对象,Unmarshal()函数则将json字符串转换为struct类型- 对于一个已有的结构体,只要保证每个字段的第一个字母是大写,也就是是公开字段,就可以序列化,序列化的风格也是首字母大写,但也可以在结构体的变量名后加一个
json:小写后的变量名
- 对于一个已有的结构体,只要保证每个字段的第一个字母是大写,也就是是公开字段,就可以序列化,序列化的风格也是首字母大写,但也可以在结构体的变量名后加一个
2.16 时间处理
go语言提供了特定的包time来支持时间处理操作。- 时间处理主要通过
time.Time结构体来实现,它表示一个本地或UTC时间,并且包含了大量的方法可以实现时间处理,例如比较两个时间、获取和设置时区、获取时间偏移量等等 time.now()可以来获取当前时间,time.date去构造一个带时区的时间,构造完的时间。上面有很多方法来获取这个时间点的年月日小时分钟秒- 也能用
.Sub去对两个时间进行减法,得到一个时间段。时间段又可以去得到它有多少小时,多少分钟、多少秒 - 在和某些系统交互的时候,我们经常会用到时间戳,可以用
.UNIX来获取时间戳 time.Sleep()可以让程序进入休眠或者延时
2.17 进程信息
- 用
os.Argv来得到程序执行的时候的指定的命令行参数 - 用
os.Getenv("PATH")获取环境变量 exec.Command是一个用来创建及控制进程的高级函数,它可以用来执行系统内部或外部命令,可以改变进程的输入输出和环境变量。- 其是一个接受参数的函数,其中第一个参数是要执行的命令字符串,后面的参数是执行命令时的参数。。