@@ -35,7 +35,7 @@ Credit: 基于 @pyz 的 2022 暑培讲稿,少量修改而成。
35
35
36
36
推荐使用 JetBrains 公司的 GoLand 作为 IDE,对于大学生而言,可以获取免费的学生版。也可使用 VSCode + Go 语言插件。
37
37
38
- ??? note "验证学生身份"
38
+ !!! note "验证学生身份"
39
39
40
40
对于清华大学的学生,在使用校园邮箱验证 JetBrains 学生身份时,请将邮箱后缀替换为 `@mails.thu.edu.cn`。
41
41
@@ -131,9 +131,9 @@ func main() {
131
131
132
132
我们可以看到,` main` 函数里调用了 ` fmt` 包的 ` Println` 方法进行输出。
133
133
134
- !!! notes
134
+ !!! notes
135
135
136
- 一个语言中的方法有很多,即使是熟悉标准库中的常用方法都需要大量的编程练习。作为一篇入门教程,掌握基本的语法即可,无需纠结自己为何记不住相应的方法。多上网冲浪,和他人沟通,就能逐渐掌握各类方法。
136
+ 一个语言中的方法有很多,即使是熟悉标准库中的常用方法都需要大量的编程练习。作为一篇入门教程,掌握基本的语法即可,无需纠结自己为何记不住相应的方法。多上网冲浪,和他人沟通,就能逐渐掌握各类方法。
137
137
138
138
在这里讲一下 Go 的运行机制:
139
139
@@ -597,26 +597,26 @@ func HandleLogin(g *gin.Context) {
597
597
598
598
1 . 路由组的概念和中间件
599
599
600
- 我们使用了 ` r.Group()` 声明一个路由组 /verified ,在这个路径下所有的访问都需要先执行 ` Verifiy()` 这一 handler function。
600
+ 我们使用了 ` r.Group()` 声明一个路由组 /verified ,在这个路径下所有的访问都需要先执行 ` Verifiy()` 这一 handler function。
601
601
602
- Handler function 是递归执行的,可以认为 ` .Next()` 是这个递归向深层的一个标志,而 ` Abort()` 则 是结束整个访问,直接返回,类似递归中的 ` return` 。
602
+ Handler function 是递归执行的,可以认为 ` .Next()` 是这个递归向深层的一个标志,而 ` Abort()` 则 是结束整个访问,直接返回,类似递归中的 ` return` 。
603
603
604
604
605
605
2 . 登录赋予 cookie
606
606
607
- 这里,示例代码使用访问者 IP 的 SHA256 分配 cookie 值。赋予用户这个 cookie 的同时,服务器端也要保存这个 cookie 到内存中,从而实现快速的信息获取。在这里,这个信息是由 ` record` 这一 map 数据结构存储的。
607
+ 这里,示例代码使用访问者 IP 的 SHA256 分配 cookie 值。赋予用户这个 cookie 的同时,服务器端也要保存这个 cookie 到内存中,从而实现快速的信息获取。在这里,这个信息是由 ` record` 这一 map 数据结构存储的。
608
608
609
- !!! notes " 关于 Cookie"
609
+ !!! notes " 关于 Cookie"
610
610
611
- 此处我们使用访问者 IP 的 SHA256 作为 cookie,这显然是不妥当的,但作为示例未尝不可。在实际场景中会有更稳妥的算法和合适的 cookie 过期机制。
611
+ 此处我们使用访问者 IP 的 SHA256 作为 cookie,这显然是不妥当的,但作为示例未尝不可。在实际场景中会有更稳妥的算法和合适的 cookie 过期机制。
612
612
613
613
3 . Cookie 鉴权和存储信息
614
614
615
- ` Verify()` 中间件使用 cookie 存在、且在 record 中作为合法登录的标志,实际应用中我们可能要考虑 cookie 是否过期等其他因素。两个数值操作 ` accumulate` 和 ` multiply` 则对用户的信息作了进一步更改与存储。
615
+ ` Verify()` 中间件使用 cookie 存在、且在 record 中作为合法登录的标志,实际应用中我们可能要考虑 cookie 是否过期等其他因素。两个数值操作 ` accumulate` 和 ` multiply` 则对用户的信息作了进一步更改与存储。
616
616
617
- 这看起来是一个“有记忆的”后端了,但这还远远不够——存储在内存里的信息随着掉电就将丢失。我们不希望 B 站服务器一停机,收藏夹里的东西没了,学校也不希望服务器一停电,学生成绩没了。因此,我们需要用 GORM 来对接数据库。
617
+ 这看起来是一个“有记忆的”后端了,但这还远远不够——存储在内存里的信息随着掉电就将丢失。我们不希望 B 站服务器一停机,收藏夹里的东西没了,学校也不希望服务器一停电,学生成绩没了。因此,我们需要用 GORM 来对接数据库。
618
618
619
- 当然 cookie 信息还有可能有被篡改的危险,我们需要更鲁棒的方式分级存储不同敏感程度的用户信息。我们需要我们的后端和数据库做交互。
619
+ 当然 cookie 信息还有可能有被篡改的危险,我们需要更鲁棒的方式分级存储不同敏感程度的用户信息。我们需要我们的后端和数据库做交互。
620
620
621
621
### 4 . GORM 和 GORM 的 AutoMigrate
622
622
@@ -886,7 +886,7 @@ func PrintTask1() {
886
886
887
887
其次,锁是一个不同线程之间的约定,它代表了执行一个公共操作 (代码中,这个“公共操作”是对 shared 这个变量加 1) 的机会,尽管这个操作能被很多个线程 (或者是 goroutine) 执行,但我们希望它在某一个时刻至多只有一个线程在执行。所以可以认为锁的管控范围是执行这个公共操作的机会。
888
888
889
- 最后,虽然看起来锁是一个全局变量,和其他的全局变量没什么区别,但不能用一个全局变量替代他 ,执行它的功能。因为锁的实现依赖于更底层的帮助,比如**线程级别的锁可能依赖操作系统的调度**,来实现互斥的访问。
889
+ 最后,虽然看起来锁是一个全局变量,和其他的全局变量没什么区别,但不能用一个全局变量替代它 ,执行它的功能。因为锁的实现依赖于更底层的帮助,比如**线程级别的锁可能依赖操作系统的调度**,来实现互斥的访问。
890
890
891
891
### 3. Produce-Consume
892
892
0 commit comments