go语言的一些特点:
只有for循环
不需要第三方库
switch 类似于 if else
socks5代理 原理:
协程
线程:用户态,轻量级线程,栈MB级别。
协程:内核态,线程跑多个协程,栈KB级别。
go语言一次可创建上万个协程
为函数创建协程,只需要在调用函数时在其前面加上go关键字:
Goroutine提倡通过通信共享内存而不是通过共享内存实现通信。
共享内存(互斥变量)方式的性能较低。
通道(channel)
make(chan 元素类型,[缓冲大小])
•无缓冲通道(同步通道) make(chan int)
•有缓冲通道 make(chan int,2) 有“快递仓”,仓满时阻塞
同步(Sync)
解决并发安全问题:加锁
在go中也可以使用wait group来解决并发安全问题
依赖管理
GOPATH
GOPATH是Go语言支持的一个环境变量,value是GO项目的工作区。 目录有以下结构:
- bin:存放Go项目编译生成的二进制文件。
- pkg:存放编译的中间产物,加快编译速度。
- src:存放Go项目的源码:。
弊端:无法实现package多版本控制
解决:项目目录下增加vendor文件,所有依赖包以副本形式放在里面。每个项目引入一份依赖的副本。
vendor弊端:无法控制依赖的版本。更新项目有可能出现依赖冲突,导致编译出错。
Go Module
-
通过go.mod 文件管理依赖包版本
-
通过go get/go mod 指令工具管理依赖包
终极目标:定义版本规则和管理项目依赖关系
依赖管理三要素:
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
依赖配置-go.mod
依赖配置-version
每次提交都会生成伪版本号
indirect 非直接依赖
incompatible
依赖分发-变量Proxy
本地工具-go get
本地工具-go mod
项目测试
测试是避免事故的最后一道屏障。
单元测试
单元测试-规则
评估测试:覆盖率。保证测试的完备性。
- 一般覆盖率:50%一60%,较高覆盖率80%+。
- 测试分支相互独立、全面覆盖。
- 测试单元粒度足够小,函数单一职责。
单元测试-依赖
幂等:重复运行一个case的结果是一样的。
稳定:单元测试相互隔离。
单元测试-文件处理
package test
import (
"bufio"
"os"
"strings"
)
func ReadFirstLine() string {
open, err := os.Open("log")
defer open.Close()
if err != nil {
return ""
}
scanner := bufio.NewScanner(open)
for scanner.Scan() {
return scanner.Text()
}
return ""
}
func ProcessFirstLine() string {
line := ReadFirstLine()
destLine := strings.ReplaceAll(line, "11", "00")
return destLine
}
package test
import (
"bou.ke/monkey"
"github.com/stretchr/testify/assert"
"testing"
)
func TestProcessFirstLine(t *testing.T) {
firstLine := ProcessFirstLine()
assert.Equal(t, "line00", firstLine)
}
func TestProcessFirstLineWithMock(t *testing.T) {
monkey.Patch(ReadFirstLine, func() string {
return "line110"
})
defer monkey.Unpatch(ReadFirstLine)
line := ProcessFirstLine()
assert.Equal(t, "line000", line)
}
Mock测试
快速Mock函数
- 为一个函数打桩
- 为一个方法打桩
用一个函数替换一个函数
可以不再依赖本地文件
package test
import (
"bou.ke/monkey"
"github.com/stretchr/testify/assert"
"testing"
)
func TestProcessFirstLine(t *testing.T) {
firstLine := ProcessFirstLine()
assert.Equal(t, "line00", firstLine)
}
func TestProcessFirstLineWithMock(t *testing.T) {
monkey.Patch(ReadFirstLine, func() string {
return "line110"
})
defer monkey.Unpatch(ReadFirstLine)
line := ProcessFirstLine()
assert.Equal(t, "line000", line)
}
基准测试
-
优化代码,需要对当前代码分析
-
内置的测试框架提供了基准测试的能力
项目实践
需求描述
需求分析
ER图
分层结构:
整体分为三层,repository数据层, service逻辑层, controoler视图层。
数据层关联底层数据模型,也就是这里的model,封装外部数据的增删改查,我们的数据存储在本地文件, 通过文件操作拉取话题, 帖子数据;数据层面向逻辑层,对service层透明, 屏蔽下游数据差异,也就是不管下游是文件,还是数据库,还是微服务等,对service层的接模型是不变的。
Servcie逻辑层处理核心业务逻辑,计算打包业务实体entiy,对应我们的需求,就是话题页面,包括话题和回帖列表,并上送给视图层;
Cortroller视图层负责处理和外部的交互逻辑,以view视图的形式返回给客户端,对于我们需求,我们封装json格式化的请求结果,api形式访问就好。
- 数据层:数据Model,外部数据的增删改查
- 逻辑层:业务Entity,处理核心业务逻辑输出
- V视图层:视图view,处理和外部的交互逻辑
组件工具:
-
Gin 高性能go web框架 github.com/gin-gonic/g…
-
Go Mod
go mod init
go get gopkg.in/gin-gonic/gin.v1@v1.3.0
gin, 高性能开源的go web框架,我们基于gin搭建web服务器,在课程手册应该提到了,这里我们只是简单的使用,主要涉及路由分发,不会涉及其他复杂的概念。
因为我们引入了web框架,所以就涉及go module依赖管理,如前面依赖管理课程内容讲解,我们首先通过go mod是初始化go mod管理配置文件,然后go get下载gin依赖,这里显示用了V1.3.0版本。
有了框架依赖,我们只需要关注业务本身的实现,从reposity --> service --> contoller我们一步步实现。希望大家能跟上我的节奏,从0~1 实现这个项目,如果时间问题,大家可以一步步copy一下,主要是走一半开发思路。