《使用Gin框架构建分布式应用》阅读笔记:p77-p87

news/2024/10/19 8:51:04

《用Gin框架构建分布式应用》学习第5天,p77-p87总结,总计11页。

一、技术总结

1.Go知识点

(1)context

2.on-premises software

p80, A container is like a separate OS, but not virtualized; it only contains the dependencies needed for that one application, which makes the container portable and deployable on-premises or on the cloud。

premises的意思是“the land and buildings owned by someone, especially by a company or organization(归属于某人(尤指公司、组织)的土地或建筑物)”。简单来说 on-premises software 指的是运行在本地的服务(软件)。

wiki 对这个名称的定义很好,这里直接引用“On-premises software (abbreviated to on-prem, and often written as "on-premise") is installed and runs on computers on the premises of the person or organization using the software, rather than at a remote facility such as a server farm or cloud”。

3.openssl rand命令

openssl rand -base64 12 | docker secret create mongodb_password
-

rand 命令语法:

openssl rand [-help] [-out file] [-base64] [-hex] [-engine id] [-rand files] [-writerand file] [-provider name] [-provider-path path] [-propquery propq] num[K|M|G|T]

12对应 num参数。rand详细用法参考https://docs.openssl.org/3.4/man1/openssl-rand/。对于一个命令,我们需要掌握其有哪些参数及每个参数的含义。

4.查看docker latest tag对应的版本号

(1)未下载镜像

打开latest tag对应的页面,如:https://hub.docker.com/layers/library/mongo/latest/images/sha256-e6e25844ac0e7bc174ab712bdd11bfca4128bf64d28f85d0c6835c979e4a5ff9,搜索 VERSION,然后找到版本号。

(2)已下载镜像

使用 docker inspect 命令进行查看。

# docker inspect d32 | grep -i version"DockerVersion": "","GOSU_VERSION=1.17","JSYAML_VERSION=3.13.1","MONGO_VERSION=8.0.1","org.opencontainers.image.version": "24.04"

5.mongo-go-driver示例

书上代码使用的mongo-go-driver v1.4.5,现在已经更新到了v2.0.0,导致有些代码无法运行,建议使用最新版。这里还得再吐槽下 Go 生态圈的文档写得太糟糕了。示例:

client, _ := mongo.Connect(options.Client().ApplyURI("mongodb://localhost:27017"))
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()_ = client.Ping(ctx, readpref.Primary())

个人认为,上面的代码 err 就不应该忽略掉。而应该是:

package mainimport ("context""github.com/gin-gonic/gin""github.com/rs/xid""go.mongodb.org/mongo-driver/v2/mongo""go.mongodb.org/mongo-driver/v2/mongo/options""go.mongodb.org/mongo-driver/v2/mongo/readpref""log""net/http""strings""time"
)type Recipe struct {ID           string    `json:"id"`Name         string    `json:"name"`Tags         []string  `json:"tags"`Ingredients  []string  `json:"ingredients"`Instructions []string  `json:"instructions"`PublishAt    time.Time `json:"publishAt"`
}var recipes []Recipefunc init() {// 方式1:使用内存进行初始化// recipes = make([]Recipe, 0)// file, err := os.Open("recipes.json")// if err != nil {// 	log.Fatal(err)// 	return// }// defer file.Close()//// // 反序列化:将json转为slice// decoder := json.NewDecoder(file)// err = decoder.Decode(&recipes)// if err != nil {// 	log.Fatal(err)// 	return// }// 方式2:使用 MongoDB 存储数据ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()// 创建连接,这里的 err 针对的是 URI 错误client, err := mongo.Connect(options.Client().ApplyURI("mongodb1://admin:admin@localhost:27017"))if err != nil {log.Fatal("MongoDB connect error: ", err)}// 判断连接是否成功if err := client.Ping(ctx, readpref.Primary()); err != nil {log.Fatal("MongoDB Ping error: ", err)}log.Println("Connected to MongoDB successfully.")}// swagger:route POST /recipes  createRecipe
//
// # Create a new recipe
//
// Responses:
//
//	200: recipeResponse
//
// NewRecipeHandler 新增recipe,是按照单个新增,所以这里名称这里用的是单数
func NewRecipeHandler(c *gin.Context) {var recipe Recipeif err := c.ShouldBindJSON(&recipe); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}recipe.ID = xid.New().String()recipe.PublishAt = time.Now()recipes = append(recipes, recipe)c.JSON(http.StatusOK, recipe)
}// swagger:route GET /recipes  listRecipes
// Returns list of recipes
// ---
// produces:
// - application/json
// responses:
// '200':
// description: Successful operation
// ListRecipesHandler 差下recipes,因为是查询所有,所以名称这里用的是复数
func ListRecipesHandler(c *gin.Context) {c.JSON(http.StatusOK, recipes)
}// UpdateRecipeHandler 更新 recipe,因为是单个,所以使用的是单数。
// id 从 path 获取,其它参数从 body 获取。
func UpdateRecipeHandler(c *gin.Context) {id := c.Param("id")// 数据解码var recipe Recipeif err := c.ShouldBindJSON(&recipe); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}// 判断 id 是否存在index := -1for i := 0; i < len(recipes); i++ {if recipes[i].ID == id {index = i}}// 如果 id 不存在if index == -1 {c.JSON(http.StatusNotFound, gin.H{"error": "recipe not found"})return}// 如果 id 存在则进行更新recipes[index] = recipec.JSON(http.StatusOK, recipe)
}// DeleteRecipeHandler 删除 recipe: 1.删除之前判断是否存在,存在就删除,不存在就提示不存在。
func DeleteRecipeHandler(c *gin.Context) {id := c.Param("id")index := -1for i := 0; i < len(recipes); i++ {if recipes[i].ID == id {index = i}}if index == -1 {c.JSON(http.StatusNotFound, gin.H{"message": "recipe not found"})return}recipes = append(recipes[:index], recipes[index+1:]...)c.JSON(http.StatusOK, gin.H{"message": "recipe deleted",})
}// SearchRecipesHandler 查询 recipes
func SearchRecipesHandler(c *gin.Context) {tag := c.Query("tag")listOfRecipes := make([]Recipe, 0)for i := 0; i < len(recipes); i++ {found := falsefor _, t := range recipes[i].Tags {if strings.EqualFold(t, tag) {found = true}if found {listOfRecipes = append(listOfRecipes, recipes[i])}}}c.JSON(http.StatusOK, listOfRecipes)
}
func main() {router := gin.Default()router.POST("/recipes", NewRecipeHandler)router.GET("/recipes", ListRecipesHandler)router.PUT("/recipes/:id", UpdateRecipeHandler)router.DELETE("/recipes/:id", DeleteRecipeHandler)router.GET("/recipes/search", SearchRecipesHandler)err := router.Run()if err != nil {return}
}

二、英语总结

1.ephemeral

p79, I opted to go with Docker duce to its popularity and simplicity in runing ephermeral environment.

(1)ephemeral: ephemera + -al。

(2)ephemera: epi-("on") + hemera("day"), lasting one day , short-lived"。

三、其它

从目前的阅读体验来看,作者默认读者充分掌握Golang,丝毫不会展开介绍。

四、参考资料

1. 编程

(1) Mohamed Labouardy,《Building Distributed Applications in Gin》:https://book.douban.com/subject/35610349

2. 英语

(1) Etymology Dictionary:https://www.etymonline.com

(2) Cambridge Dictionary:https://dictionary.cambridge.org

欢迎搜索及关注:编程人(a_codists)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/72867.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

排序算法 - 快速排序

排序算法 - 快速排序概要快速排序(Quicksort)是对冒泡排序算法的一种改进。快速排序是一种基于分而治之的排序算法。它的基本思想是: 选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法…

学习groovy基础

简介 Groovy 是一种 JVM 语言,它可以编译与 Java 相同的字节码,然后将字节码文件交给 JVM 去执行,并且可以与 Java 无缝地互操作,Groovy 可以透明地与 Java 库和代码交互,可以使用 Java 所有的库。 Groovy 也可以直接将源文件解释执行 它还极大地清理了 Java 中许多冗长的…

高级语言程序设计第三次作业

这个作业属于哪个课程:https://edu.cnblogs.com/campus/fzu/2024C 这个作业要求在哪里: https://edu.cnblogs.com/campus/fzu/2024C/homework/13284 学号:102400127 姓名:王子涵 4.8q2 打印引号的时候一开始忘了 然后在写d小题的时候宽度不知道怎么处理 后来询问了同学解决…

计量经济学(十)——正态性检验(Normality Test)

img { display: block; margin-left: auto; margin-right: auto } table { margin-left: auto; margin-right: auto } 正态性检验(Normality Test)是一种用于判断数据是否服从正态分布的重要统计方法,广泛应用于时间序列分析、回归分析等模型的构建与诊断中。许多统计模型,…

Response web登录操作 -2024/10/17

响应行设置响应状态码: void setStatus(int sc);设置响应头键值对: void setHeader(String name,String value);response实现重定向resp.setStatus(302);resp.setHeader("location","https://www.4399.com");前端a.html登录,将结果传给后端,用request接收…

Kail从入门到入狱第二课:mkdir、touch、vim、cat命令的基本应用

如果是日常生活,请不要使用root,因为root可以做任何事情比如"格式C盘" 创建目录:mkdir 很简单,在当前工作目录创建一个目录,如图所示测试:请说出cd /test的含义 今天我们将使用图形界面,请打开命令行创建文件:touch touch filename可以看到成功创建 文本编辑…

地平线与英伟达工具链 PTQ 工具功能参数对比与实操

1.理论简介在阅读本文之前,希望大家对 PTQ(Post-Training Quantization) 训练后量化有一定的了解~地平线 OpenExplorer 和 NVIDIA TensorRT 是两家公司为适配自己的硬件而开发的算法工具链,它们各自具有独特的特点和优势。分开看的时候,网上有很多资料,但却没找到将他们…

公网Linux环境搭建frp实现内网穿透

前提: 本实验为一台ubuntu22操作系统云主机 脚本适用于安装平台:CentOS、Debian、Ubuntu FRP项目地址:https://github.com/fatedier/frp FRP一键脚本地址:https://github.com/MvsCode/frps-onekey1、FRP服务器端一键安装脚本(脚本在本文最后有,如果在服务器上无法获取到下…