go从入门到进阶的笔记

做个流水账样式的笔记吧。在工作中用到go,但毕竟不是主力语言,有些地方可能用不到。

业务需要又必须有地方用到go,最近打算改造现有的c++服务,用go替换其中的业务部分。

最近看了徐波老是的go从入门到进阶。做了个流水笔记。

根据这些知识点写了一堆代码,比较丑陋,我就不贴了啊。

# 知识点大全

## 1 初始语言

新,简单,快,风格清晰,标准库强大

## 2 基本语法

变量的声明,赋值

匿名变量

数据类型:整型,浮点型,布尔型,字符串,
字符,
切片

类型转换

指针:类型指针,切片

1 声明指针
2 new()

变量生命周期:栈,堆

逃逸分析:自动决定变量分配方式,提高运行效率

1 分析逃逸 -gcflags "-m -l"
2 取址发生逃逸分析
3 原则
1 变量是否被取地址
2 变量是否发生了逃逸

字符串提供的操作

长度,取地址,连接

格式化

%v %+v %#v $T %% %b %o %d %x $X %U %f %p

常量const

枚举iota

类型别名和类型定义

type NewInt int
type IntAlias = int

非本地类型无法添加方法

## 3 容器:存储和组织数据的方式

数组:固定长度的连续内存区域

切片:动态分配大小的连续空间

1 数组或者切片产生
2 make
3 append copy 删除:

map

1 make
2 range
3 delete
4 清除,依赖垃圾回收

sync.Map

1 初始化
2 Store, Load, Delete
3 Range

container/list

1 初始化list.New()
2 PushBack PushFront
3 Next

## 4 流程控制

if
for

for range【array slice string map channel】

switch fallthrough

goto break continue


## 5 函数

函数一等公民: 值传递,匿名函数,闭包,满足接口

声明函数

1函数支持多值返回值
2支持直接返回变量

结构体在函数中是值传递

函数可以当做值

匿名函数

函数类型实现接口,函数赋值给接口

闭包:函数+引用环境

可变参数

...interface{}

延迟执行语句 defer

错误无处理 error

type error interface{Error() string}

panic 恐慌和recover


## 6 结构体

new 或 & 类型的指针

定义结构体

实例化结构体

1 var v1 T
2 new(T)
3 &T{}

初始化结构体的成员变量

1 初始多个值
2 初始化匿名对象

模拟构造函数

嵌入式模拟父级构造函数

方法

func (接收器类型) 方法名(参数列表)(返回参数){}

方法接收器

1 指针接收器

定义基本类型同名类型,添加方法

类型内嵌

1 可以直接访问内嵌的成员变量
2 字段名就是它的类型名

内嵌的组合


## 7 接口

声明接口,接口的命名规范

接口的实现条件:1 格式完全一样 2 方法都被实现

类型和接口的关系

使用接口抽象业务逻辑

接口嵌套

接口和类型间的转换:接口转类型,类型转接口

t := i.(T)

空接口类型 interface{}

1 值存储到空接口
2 空接口取值 i.(int)

空接口值比较

1 不同类比较结果不同,不能比较动态值

空类分支 (interface{}).(type)

## 8 包

GOPATH环境变量,提供项目的工作目录

多个GOPATH

创建包package

1 一个目录下的同级文件归属一个包
2 包名可以与目录不同
3 无main包不输出可执行文件

导出标识符:大写

导入包import

1 包别名 name xxx
2 匿名导入包 _ "xxx"

包的初始化 init

1 一个包一个
2 初始化顺序

工厂模式管理多个包的结构体


## 9 并发

创建协程go

使用匿名函数创建协程

runtime.GOMAXPROCS()设置核心数量


通道chan

make(chan XX)

通道发送数据:通道<-数据

通道接收数据:数据 :=<-通道

data,ok :=<-ch
for data :=range ch{}

单向通道 只发送:chan<-

单向通道 只接收:<-chan

带缓存的通道

通道的多路复用select

time.After 计时器

time.NewTicker 定点计时器

关闭通道 close


go run -race 检测竞争


同步之atomic

同步之互斥锁 sync.Mutex

sync.Mutex
sync.RWMutex


同步之等待组 sync.WaitGroup


## 10 反射

反射是指在程序运行期间对程序本身进行访问和修改的能力。

反射的类型对象 reflect.Type

reflect.TypeOf(a)

反射的类型Type,系统原生类型

反射的种类Kind,类型归属的种类

reflect.Elem获取指针指向的元素的类型

反射获取结果提的成员

Field(i)StructField
NumField()int
FieldByName(name)(StructField,bool)
FieldByIndex(index []int) StructField
FieldByNameFunc(match func(string)bool)(StructField,bool)

StructField

Name,PkgPath, Type, Tag, Index, Anonymous

StructTag

Get(key)string, Lookup(key)(string,bool)

反射的值对象reflect.Value

使用反射对象包装任意值 reflect.ValueOf(rawValue)

从反射值获取被包装的值

Interface()interface{}
Int(),Uint(),Float(),Bool(),Bytes(),String()

使用反射访问结构体的成员字段的值

Field(i)Value
NumberField()
FieldByName(name)Value
FieldByIndex(index []int)Value
FieldByNameFunc(match func(string)bool)Value

反射对象的空和有效性判断

isNil, isValid

使用反射值对象获取变量的值【先寻址,再修改】

Elem()类似*
Addr()类似&
CanAddr()bool
CanSet()bool

使用反射值对象修改相关的方法

SetInt,SetUint,SetFloat,SetBool,
SetBytes,SetString

通过类型创建类型的实例

1 reflect.New(typeOfA)

使用反射调用函数

funcValue.Call(xx)


## 11 编译与工具

go build

-v 包名
-p 并发编译
-a 强制重新构建
-race 开启竞态检测

go run

go install 编译并安装

go get

go test

文件 XX_test
方法 TestXX(t *testing.T)

test指定方法

go test -v -run TestA xxxx_test.go

终止测试 t.FailNow()

基准测试

Benchmark_Add(b *testing.B) b.N
go test -v -bench=. xxxx_test.go

自定义bench时间 -bench -benchtime=5s

测试内存 -bench=Alloc -benchmem xxx_test.go

控制计时器

b.ResetTimer() 重置
b.StopTimer() 停止
b.StartTimer() 开始

性能分析 go pprof

1 安装Graphviz 图形的工具包
2 runtime.pprof可以使用,但是不太方便
3 go get github.com/pkg/profile
4 go build
5 go tool pprof --pdf xxx xx.pprof > xx.pdf

## 12 避坑与技巧

### 合理地使用并发特性

1 了解goroutine的生命期再创建goroutine

创建,退出

2 避免在不必要的地方使用通道

1 通道为了保证goroutine并发访问,也需要做锁操作

3 反射:性能和灵活性的双刃剑

1 使用原生代码,避免反射
2 提前缓存反射对象对性能帮助较大
3 避免使用反射函数调用,实在需要时,提前缓冲函数参数列表,并尽量少使用返回值

4 nil只能被赋值给指针和接口

接口底层 type和data,都为nil是才是nil

发现返回nil时直接返回nil


基于哈希值的多键索引及查询

1 字符串转哈希值
2 查询键值


优雅的处理TCP粘包


猜你喜欢

转载自www.cnblogs.com/beckbi/p/11619288.html