跟随 Go by Example 中文版 (gobyexample-cn.github.io) 项目复习Golang语言
- 基本数据
- Hello world
- value
- variable
- constant
- 基本控制
- for
- if/else
- switch
- 高级数据结构
- array
- slice
- map
- 🩹 range
- 函数
- 普通
- 多值返回
- 变参函数
- 迭代
- 派生类型
- 指针
- 结构体
- 方法
- 接口
- 错误处理
- 错误处理
- 协程与通道
- 协程
- WaitGroup
- 通道
- 通道缓冲
- 通道同步
- 通道方向
- 通道选择器
- 超时处理
- 非阻塞通道
- 通道关闭
- 通道的遍历
- Timer&Ticker
- 速率限制
- 原子操作
- 原子计数
- 互斥锁
- 状态协程
- 协程
- 排序
- 错误与异常
- 字符串相关
- 操作
- 格式化
- 正则表达式
- JSON
- XML
- 时间
- time
- 时间戳
- 格式化
- 随机数
- 解析数字
- URL解析
- SHA1哈希
- Base64编码
- I/O及文件操作
- 读文件
- 写文件
- 行过滤器
- 文件路径
- 目录
- 临时文件和目录
- 单元测试
- 命令行
- 参数
- 标志
- 子命令
- 环境变量
- HTTP
- HTTP 客户端
- HTTP 服务器端
- Context
- 进程
- 生成进程
- 执行进程
- 信号
- 退出
| 知识点 | 注意内容 | 链接 |
|---|---|---|
| Golang值基本类型 | 基本类型 | |
| Golang变量 | 变量 | |
| Golang常量 | 常量 | |
| Golang for循环 | for循环 | |
| Golang if/else判断 | 1. 花括号必需;2. 没有三目运算 | if/else判断 |
| Golang switch分支 | 1.任何类型 2.可以为表达式 3.break/fallthrough 4. 类型判断算法 | switch分支 |
| Golang 数组 | 1.长度固定 2.空零值 | 数组 |
| Golang 切片 | 2.长度可以不固定 2. make初始化 3. append操作 4.copy操作 | 切片 |
| Golang map | map | |
| Golang range | 1.可以只迭代map的key 2.在字符串中迭代 unicode | |
| Golang 函数 | 函数 | |
| Golang 指针 | 参考C | 指针 |
| Golang struct | struct | |
| Golang 方法 | Go会自动处理值与指针之间的转换 | 方法 |
| Golang 接口 | 1. 实现多类 2.intetface{} | |
| Golang 错误处理 | 错误处理 | |
| Golang 协程 | 协程 | |
| Golang 通道 | 通道 | |
| Golang 定时器与打点器 | Timer&Ticker | |
| Golang 排序 | 排序 | |
| Golang 错误与异常 | 错误与异常 | |
| Golang 字符串操作 | 字符串操作 | |
| Golang 正则表达式 | 正则表达式 | |
| Golang JSON | Json | |
| Golang XML | XML | |
| Golang 时间 | 时间 | |
| Golang 随机数 | 随机数 | |
| Golang 解析数字 | 解析数字 | |
| Golang URL解析 | URL解析 | |
| Golang SHA1哈希 | SHA1哈希 | |
| Golang Base64编码 | base64编码 | |
| Golang IO操作 | IO操作 | |
| Golang 单元测试 | 单元测试 | |
| Golang 命令行 | 命令行 | |
| Golang HTTP | HTTP | |
| Golang 进程 | 进程 |
- var b bool = true
- 逻辑运算符
- 与 &&
- 或 ||
- 非 !
- 基于架构的类型
- int uint
- 64位 64bit
- 32位 32bit
- uintptr
- 足够存放一个指针即可
- int uint
- 与操作系统架构无关类型
- 有符号整数
- int8
- int16
- int32
- int64
- 无符号整数
- uint8
- uint16
- uint32
- uint 64
- 浮点数
- float32
- float64
- 有符号整数
- 进制
- 077 八进制
- 0xFF 十六进制
- 复数
- complex64
- complex128
- 位运算
- 要求
- 整数
- 等位长
- 二元运算符
- 按位与 &
- 按位或 !
- 按位异或 ^
- 一元运算符
- 按位补足 ^
- 位左移 <<
- 位右移 >>
- 要求
- ASCII字符
- byte
- Unicode字符
- int \u十六进制
- 特性
- 值类型
- 值不可变
- 分类
- 解释字符串
- 双引号
- 非解释字符串
- 反引号
- 解释字符串
- var
- var identifier type
- 自动赋值为0值
- 骆驼命名法
- 全局变量
- 局部变量
- const
- const identifier [type] = value
- const Pi = 3.14159
- 编译时刻值要确定
- 除了内置函数 例如len()
- 可以执行任意精度的运算
- 没有确定类型
- 根据上下文需要自动确定类型
- for 初始化语句; 条件语句; 修饰语句 {}
- 无限循环 for{}
- for-range
- for pos, char := range str {}
- if initialization; condition { // do something }
- if condition { // do something } else { // do something }
- if condition1 {
// do something
} else if condition2 {
// do something else
} else { // catch-all or default } - 格式要求
- 左括号和条件同行
- 右括号和下一级同行
- switch var1 { case val1: ... case val2: ... default: ... }
- 特性
- var 可以是任何类型
- 可以为表达式
- 各个直接的类型相同
- 不需要单独使用break
- fallthrough 关键字接着执行
- 相同唯一类型
- 原始类型
- 编号
- 长度固定
- var identifier [len]type
- var arr=new([5]int)
- arr类型为 *[5]int
- 长度可变的数组
- 计算容量 cap()
- 定义
- var identifier []type
- append
- copy
-
引用类型
-
初始化
- 初始化方法
- map literals
- maplit = map[string]int{"one":1,"two":2}
- 引用类型
- mapcreat:=make(map[string]int)
- 不要使用new
- map literals
- 未初始化
- nil
- 初始化方法
-
声明与赋值
- 要求
- key
- 可以:int float string 指针 接口类型等
- 可以:结构体
- key()
- hash()
- 不可以:数组 切片 结构体
- value
- 任意值
- 切片(一对多)
- map1 := make(map[int][]int)
- map1 := make(map[int]*[]int)
- 切片(一对多)
- 函数
- 任意值
- key
- 值赋值
- map1[key] =value
- val :=map[key]
- var map map[keytype] valuetype
- 要求
-
容量
- 容量不定
- 动态伸缩
- 可以在make时候进行指定
- mapcreated := make(map[string]int,100)
- 到达容量上限会自动增加
- 出于性能考虑
- 尽量表明容量
-
存在判断
- value,IsPresent = map[key]
-
删除
- delete(map1,key1)
-
循环
- for key value := range map{ }
-
map 切片
-
- 分配切片
- maplist := make([] map[string]int,100)
-
- 对切片的每个元素进行分配值
- for i := range mapList{ mapList[i]=map[string]int{"one":1,"two":2} }
-
-
map 排序
- 无序的
- 解决方案
- 复制到切片中
- 在切片中进行排序
-
格式
- func functionName(parameter_list) (return_value_list) { … }
-
main函数
- 无参数
- 无返回值
-
可以多值返回
-
变参函数
- ...
-
闭包,匿名函数
-
递归
- 数据结构
- 分配的数量
- 内存访问模式
- &
- nil
- 字段构成
- 名字(唯一)
- 类型
- type identifier struct { field1 type1 field2 type2 ... }
- 支持匿名字段
- type identifier struct { field1 type1 type2 ... }
- 支持内嵌结构体
- type A struct { a int } type B struct { s str A }
-
混合字面量语法
- ms := &struct1{10, 15.5, "Chris"}
- intr := Interval{0, 3} (A) intr := Interval{end:5, start:1} (B) intr := Interval{end:5} (C)
- var s T s.a = 5 s.b = 8
- 无论是值或者指针,都可以使用选择器(.)来进行访问
- 为结构体分配内存并返回指针
- var t *T = new(T)
- 附属于字段的字符串
- 使用reflect包进行访问
- 在运行时自省类型、属性和方法
- 作用在接收者(receiver) 上
- 特殊函数
- func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }
- 接收者
- 除了接口类型之外都可以
- 不使用recv 的值,可以用 _ 替换它
- 变量
- 方法被变量调用
- 函数将变量作为参数
- 使用一个明确的返回值来传递错误信息
- 通常是最后一个返回值
- error类型
- 内建接口
errors.New()构造一个基本的error值nil代表没有错误- 实现
Error()方法来自定义error类型
- 启动
- 在调用函数或者方法时,使用关键字go
- 协程的调用会立即返回
main goroutine会运行任何其他goroutine,如果main goroutine终止,则该程序将被终止,并且其他goroutine将得不到运行机会- 常常与匿名函数搭配
- M:N线程模型,M个协程运行在N个线程之上
WaitGroup等待所有的协程- main协程通过调用 wg.Add(delta int) 设置worker协程的个数,然后创建worker协程;
- worker协程执行结束以后,都要调用 wg.Done();
- main协程调用 wg.Wait() 且被block,直到所有worker协程全部执行结束后返回。
- 创建
- make(chan val-type)
- 发送
- channel <-
- 接收
- <-channel
- 发送和接收默认是阻塞式的
- 通道 默认是 无缓冲
- 只有通道准备好接收时,才进行发送
- 有缓冲的通过
- make(chan string,2) 指定缓冲两个值
- 可以使用通道来同步协程之间的执行状态
- 使用通道作为函数的参数时,可以指定通道是只读还是只写
- 选择器可以同时等待多个通道操作
- 超时处理
Time.After()
- 非阻塞通道
- 带
default子句的select语句实现
- 带
- 通道关闭
close()语句
- 遍历通道
for range
- Timer 定时器
func After(d Duration) <- chan Time- 经过时长d之后,向通道Time发送当前消息
- 返回只读通道
func AfterFunc(d Duration, f func()) *Timer- 在经过时长d之后调用函数f
- 返回Timer
func NewTimer(d Duration) *Timer- 创建新的定时器
func (t *Timer) Reset(d Duration) bool- 重置定时器,以d为触发时间
func (t *Timer) Stop() bool- 停止定时器
Timer.C定时向信道发送时间
- Ticker 打点器
func Tick(d Duration) <-chan Time- 每经过d之后,向通道发送当前时间
func NewTick(d Duration) *Ticker- 创建新的打点器
func (t *Ticker) Stop()- 停止打点器
Ticker.C定时向通道发送当前时间
sort包- 内建数据类型的排序
- 原地排序 (直接改变数据)
- 自定义排序
- 实现
sort.Interface接口的Len()Swap()Less()判断逻辑
- 实现
- 内建数据类型的排序
-
Golang中的错误与异常
- 错误 error
- 可预见的
- 会导致逻辑上的错误,或者进一步变成异常
- 异常 panic
- 不可预见的
- 导致进程异常退出
- 错误 error
-
Golang中的错误
- 本质
- 接口
- 包含
Error()函数,返回值为string
- 包含
- 接口
- 创建
errors.New(text string) error
- 装包与解包
fmt.Errorf()函数 装包 (增加上下文信息)- 无
%w,底层调用errors.New()创建错误,错误类型为*errors.errorString - 有
%w,底层实例化wrapError结构体指针。错误类型为*fmt.wrapError
- 无
errors.Unwrap()函数 解包
- 处理
- 使用多值返回
- 要么处理,要么略过
- 最佳实践
- github.com/pkg/errors
Wrap()包装底层错误,增加上下文信息,附加调用栈WithMessage()增加上下文,不附加调用栈WithStack()仅返回堆栈信息Cause()判断底层错误
- github.com/pkg/errors
- 本质
-
Golang中的异常
panic: 改变程序的控制流,调用之后立即停止当前函数的剩余代码,让程序进入恐慌,递归执行调用方的deferdefer: 会在当前函数返回前执行传入的函数,常常用于一些收尾工作(如数据库回滚,关闭文件等)recover: 可以终止恐慌,只能在defer中发挥作用
-
string包操作
| 函数用法 | 含义 |
|---|---|
Contains(obj,s) |
obj中是否包含s |
Count(obj,s) |
统计obj中s的个数 |
HasPrefix(obj,s) |
s是否是obj的前缀 |
HasSuffix(obj,s) |
s是否是obj的后缀 |
Index(obj,s) |
s在obj中的下标 |
Join(obj []string,s) |
s插入到obj中 |
Repeat(obj,n int) |
obj重复n次 |
Replace(obj,old,new,n) |
将obj中的前n(n<0时候为全部)个old替换为new |
Split(obj,s) |
以s为分隔符去分割obj |
ToLower(obj) |
将obj转为小写 |
ToUpper(obj) |
将obj转为大写 |
- 格式化
- 通用占位符
%v值的默认格式%+v类似上,但是输出结构体时会添加字段名%#v值的Go语法表示%T值类型的Go语法表示
- 常用类型
- 整数类型
%b二进制%cunicode码点表示的字符%d十进制%o八进制%q单引号的字符字面值%x十六进制,小写%X十六进制,大写%UUnicode格式
- 浮点数类型
%b无小数,二进制指数 科学计数法%e科学计数法%E科学计数法%f %F有小数,但是没有指数部分%g %G根据实际情况选择%e %E或%f
- 布尔型
%t
- 字符串类型
%s无解释字节%q无双引号围绕的字符串,由Go语法安全的转义%x %X十六进制字母,每个字节两个字符
- 指针类型
%p十六进制表示,前缀0x
- 标志
+始终打印数值的正负值-左对齐#备用格式
- 整数类型
- 通用占位符
| 函数 | 作用 |
|---|---|
Compile() |
得到一个优化过的Regexp结构 |
MustCompile() |
同上,但是使用panic代替错误 |
r.MatchString(s)/regexp.MatchString(rs,s) |
匹配测试,返回布尔值 |
r.FindString(s)/regexp.FindString(rs,s) |
字符串查找,返回完全匹配的字符串 |
FindStringIndex() |
首次匹配,返回匹配开始和结束的索引 |
FindStringSubmatch() |
返回完全匹配和局部匹配的字符串 |
FindStringSubmatchIndex() |
返回完全匹配和局部匹配的字符串索引 |
FindAllstring(s,n) |
返回所有n次匹配的字符串 |
FindAllstringSubmatchIndex() |
同上,但是返回下标 |
ReplaceAllString(s,rs) |
替换字符串 |
ReplaceAllFunc(s,func) |
同上,但是可以知道func来指定替换 |
- 编码
json.Marshal()
- 解码
json.Unmarshal()
- 编码
xml.MarshalIndent()生成可读性更好的输出结果
- 解码
xml.UnMarshal()
- 时间
- time 数据
- 组成部分
Year()年Month()月- ...
Location()时区
- 操作
Before()判断时间前After()判断时间后Rqual()判断时间相等Sub()时间相减返回durationAdd()时间加上时间段
- 时间戳
time.Now().Unix()时间戳 秒time.Now().UnixNano()时间戳 纳秒
- 组成部分
- 常见操作
time.Now()当前时间time.Date()构建timetime.Unix(sec,nsec)将时间戳转为时间- 格式化
time.Parse(form,time_str)字符串转为时间time.Now().Format()基于例子来决定日期格式
- time 数据
rand.Intn()返回随机整数rand.Float64()返回随机浮点数rand.New(rand.NewSource(time.Now().UnixNano()))更换种子
strconv.ParseFloat(str,bits)转为浮点数strconv.ParseInt(str,adv,bits)转为整数- adv: 进制,0为自动识别
strconv.ParseUnit(str,adv,bits)转为无符号整数strconv.Atoi()基础的十进制转换函数
u:=url.Parse()直接进行解析u.Scheme()schemeu.User认证信息u.User.Username()用户名u.User.Password()密码
u.Host主机名及端口u.Path路径u.Fragment片段u.RawQuery查询参数
h:=sha1.New()生成一个哈希h.Write()处理一个字符串h.Sum()得到散列值
base64.stdEncoding标准编码器EncodeToString()DecodeString()
base64.urlEncodingURL编码器
- 参考自己肝了两天的文章
- 文章
- (testing.T).Error
- 报告测试失败信息,然后继续测试
- (testing.T).Fail
- 报告测试失败信息,然后终止测试
- (*testing.T).Run
- 进行一个子集测试
- 参数
os.Args()
- 标志
- 声明
flag.String(名称,默认值,说明)flag.StringVar(&参数,名称,默认值,说明)已有的参数说明flag.Int(名称,默认值,说明)flag.Bool(名称,默认值,说明)
- 解析
flag.Parse()
- 声明
- 子命令
- 作为第一次参数传入
- 环境变量
os.GetEnv()os.SetEnv()os.Environ()
HTTP
- 客户端
- GET 请求:
http.Get()
- GET 请求:
- 服务器端
- handler
- 参数1:http.ResponseWriter 写入响应
- 参数2:http.Rquest
http.HandleFunc(路由,handler)http.ListenAndServe(地址,handler(nil为默认路由))
- handler
- 创建进程
exec.Command()创建对象进程Output()处理运行命令,等待命令,收集输出StdinPipe()/StdoutPipe()输入输出管道Write()写Close()关闭
Start()开始执行Wait()等待
- 执行进程
exec.LookPath()找到执行文件的绝对路径syscall.Exec(binary,args,env)调用执行程序
- 信号
sig := make(chan os.signal,1)创建信道signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)注册信道
- 退出
os.Exit()程序立即退出- defer不会被执行