P182 gin请求
右边部分是restful风格api
还可以带一个函数
参数要求是handlerfunc
必须要加这么一个参数
默认会去做一些事情
new是真正创建了路由
egine.Use(Logger(),Recovery()),用了2个中间件logger和recovery
也可以创建不带中间件的路由
这就会截获参数
写一个表单页面
多选框是postformarray数组
P183 gin路由
saveUploadFile保存上传的文件
只要添加这一个属性multiple就行
maxmultipartmemory限制上传大小 for循环接收文件
2个文件就上传到跟目录下
可以定义两个组v1,v2
httprouter会将所有路由规则构造一棵前缀树,这样查询就比较快,就跟mysql的btree一样
httprouter是个非常高效的小工具
P184 数据解析和绑定
解析客户端发来的请求,数据绑定是绑定在go的结构体里,所以需要先定义结构体
gin.H其实是封装了生产json的工具
获取json数据,解析之后就要判断密码是否正确
添加一个name属性
上面就是表单的截取和解析
P185 gin各种渲染
不同格式的响应
写一个模板
P186 重定向
异步处理
同步执行
P187 中间件
gin.HandlerFunc这个类型才能作为gin中间件
这样就写了一个简单的中间件
使用中间件后,一般规范是请求处理放在后面的{}里
主要是为了代码规范
next方法执行的是这个
这个new就是创建路由
先看以下logger,这个next其实是自己实现的中间件
其实就是把handler遍历了,所以index在所有handler之前都执行一下,根据handler个数遍历,然后进行处理
根据路由后面是定义的局部中间件
根据不同中间件,处理不同拦截的功能
P188 中间件练习
P189 cookie和session
cookie的用途:
1.保持用户登录状态
服务端设置了一个cookie
return 一个中间件
这回就不显示数据了
设置了一个60秒的cookie
这样就可以了
session是解决cooke弊端,服务端生产session后,把id给客户端 ,客户端只存session id,访问服务器就是用session id去到服务器拿数据
P190 中间件设计
redis的session设计
session管理者session_mgr
P191 练习
写一个memorySession
写一个构造函数,更方便获取对象,make初始化一个map
实现增删改查
实现一个总的session mgr
导入uuid包
三个函数,init,create,set
entity或model是实体类
写一个页面。
define,就是定义记载模板文件
添加新书的页面
P192 作业
创建一个表
*var db sqlx.DB申明一个db对象
initdb初始化数据库连接
插入数据
删除数据
这个是给页面定义的名字
启动服务
P193 内存session完成
session和 sessionmgr是父接口,左边和右边分别是具体的实现类,分内存级的 和redis级的
这是一个如何去创建一个session,i因为是一个大map,加一个锁,生成一个唯一ID,唯一ID转成string往map类型加进去
newMemorySession就是构造函数创建一个新的session
创建好了session就要加入到大map里
P194 中间库的完成
也是基于mvc来分项目结构
定义常量就是去定义内存里是否发生变化
下面再写一个save,从池里获取redis连接
需要把状态改回去
get方法
实现一个delete
写一个redis管理,结构体,构造函数,初始化
连接redis后进行密码验证
可以加一个连接测试
初始化返回一个redis pool
这样就是一个实现先定义接口不同版本的session中间件,可以新增一个总的初始化文件,让用户选择使用哪个版本
P195 博客数据库分析
MVC,
model就是实体(结构体)
dao:数据层(sql)
service:业务逻辑
controller: 页面控制相关
static:css js
utils:工具
view: hTML模板
main.go :入口,定义路由
文章表
5.6以上timestamp多个 字段都可以设置默认值,5.6一下多个timestamp字段只能有一个字段有默认值
分category类
comment,评论表
留言表
P196 项目搭建
新建一个项目空间
model实体类,dao数据库,service业务逻辑,controller控制器,main
首先做主页的实现
定义分类的结构体,category
定义文章结构体,这个是文章相关页,没有包含content
定义文章详情页的结构体
用于文章上下页切换的结构体
初始化数据库连接
添加ping测试连接是否成功
P197 文章的dao实现
获取多个分类
获取所有分类
写一个测试类category_test,init中的dns,数据库连接信息,parsetime=true会把mysql的时间类型,转换成go结构体中的时间类型,不加这个参数就会报错
测试获取单个分类信息
测试多个分类,就需要定义一个切片int64的切片
测试获取所有分类
一共是6个分类
实现插入文章
获取文章列表,做个分页
这就是查询所有的文章
根据id查询单个文章
定义一个查询这一类的文章
现在就针对这个接口进行测试
P198 主页的service层
获取文章和对应的分类,其实做两件事
1.获取文章列表。
2.获取文章对应的分类。
根据多个文章id,获取多个分类 id的集合
返回页面做聚合
遍历所有文章,每个文章做一个聚合,遍历进去,每个创建一个当前文章对象,文章信息就是遍历的当前文章,文章就有了对应的分类,文章的结构体里是包含分类id的,遍历分类取出分类id就可以
P199 主页功能的实现和调bug
service把数据组装好交给控制层用
根据id取所有的,主要把之前的ID字段改一下复制即可
下面是控制层,访问主页,展现所有文章和分类云。点击分类云,展示不同分类的信息
模板页面
加载文章数据,还可以加载分类数据
gin.H就是一个map,其实就是这几行代码
取消注释
总入口main文件
点击分类进行分类
这么写可以取到值
P200 复习
rpc是两个服务之间通信的协议
定义session监听后,上面定义头
P201 raft算法动画
如何让绿色发来的信息到多个节点都是8
实现一个分布式公式的协议,没有主的时候follower变成condidate去拉选票
同意之后变成主节点leader,所有更新从主节点开始
为什么叫日志复制,更新是先存到主节点的日志里,再通过这个日志同步给其他节点
选举超时时间是追随者在成为候选人之前等待的时间。选举超时被随机分配到150ms到300ms之间。避免吗同一时间一直选择不一致的,导致系统卡死
选举超时后,关注者成为候选人并开始新的选举任期…
第一票投给自己...并向其他节点发送请求投票消息。
**如果接收节点在本学期还没有投票,那么它将投票给候选节点…Continue,节点重置它的选举超时。continue
**
一旦候选人获得多数选票,就成为领袖。
leader开始向follower发送Append Entries消息。这些消息按心跳超时指定的时间间隔发送……
追随者然后响应每个Append Entries消息。这一选举任期将持续到追随者停止心跳成为候选人为止。
让我们阻止领导人,然后再选。
节点A现在是第2个任期的leader。
如果两个节点同时成为候选人,则会发生分裂投票。
让我们看一个分裂投票的例子…两个节点都开始选举同一任期。...每个节点都先到达一个跟随节点。
现在每个候选人有2票,这一任期内不能获得更多的选票
。节点将等待一次新的选举并再次尝试。节点C在第5个任期内获得了多数选票,因此成为了领头羊。
日志复制,一旦我们选出了一个leader,我们需要将系统中的所有更改复制到所有节点。这是通过使用与心跳相同的Append Entries消息来完成的。让我们来看看这个过程。
**让我们来看看这个过程。首先客户端发送一个变更给leader。更改被追加到领导的日志中,...然后在下一次心跳时将更改发送给关注者。当一个条目被大多数关注者承认时,它就被提交了,...响应被发送到客户端。
**
现在,让我们发送一个命令将值增加“2”。
我们的系统值现在更新为“7”
筏甚至可以在面对网络分区时保持一致。
让我们添加一个分区,将a、B和C、D和E.
由于我们的分裂,我们现在有两个不同任期的领导人。由于我们的分裂,我们现在有两个不同任期的领导人。
让我们添加另一个客户端,并尝试更新两个领导人。
一个客户端将尝试将节点B的值设置为“3”,节点B不能复制到大多数节点,因此它的日志条目保持未提交状态。
现在让我们h恢复网络分区。
两个节点A和B将回滚它们未提交的条目,并匹配新leader的日志。