go语言项目--实例化(图书管理)--004

发布时间:2026/8/26 19:53:17

go语言项目--实例化(图书管理)--004
v4: 并发借书系统 — 安全与并发一、版本概述v4 在 v3 的 HTTP API 基础上引入了借阅系统和并发控制。核心挑战是多人同时借同一本书时的库存超卖问题通过sync.Mutexcontext.Context超时控制解决。还引入了优雅关闭和定时逾期检查。相比 v3 的核心变化借阅系统BorrowRecord 模型 BorrowService BorrowRepository并发安全Mutex 加锁防止超借Context 超时控制借阅操作库存分离Book 新增 TotalStock/Available 字段借阅扣减 Available优雅关闭signal.Notify http.Server.Shutdown定时任务StartOverdueChecker 每 30 秒检查逾期项目结构v4/ ├── main.go # 入口优雅关闭定时任务 ├── model/ │ ├── book.go # Book 增加 TotalStock/Available │ └── borrow_record.go # 借阅记录新增 ├── repository/ │ ├── book_repo.go # 增加 DecreaseAvailable/IncreaseAvailable │ └── borrow_repo.go # 借阅仓储新增 ├── service/ │ ├── book_service.go # 图书业务 │ └── borrow_service.go # 借阅业务并发控制新增核心 ├── handler/ │ └── http_handler.go # 新增借阅路由 ├── middleware/ │ └── logger.go # 日志恢复 └── data/ ├── books.json └── borrows.json二、核心代码解读关键片段borrow_record.go — 借阅模型const(StatusBorrowedborrowedStatusReturnedreturnedStatusOverdueoverdueOverdueDays15)typeBorrowRecordstruct{IDintjson:idBookIDintjson:book_idBookTitlestringjson:book_titleUserNamestringjson:user_nameBorrowDate time.Timejson:borrow_dateReturnDate*time.Timejson:return_date,omitemptyStatusstringjson:statusIsOverduebooljson:is_overdue}设计要点状态机borrowed → returned / overdueReturnDate使用指针*time.Time零值时序列化为 null 而非零时间OverdueDays 15作为逾期阈值borrow_service.go — 并发借阅核心typeborrowServicestruct{repo*repository.BorrowRepository bookRepo*repository.BookRepository mu sync.Mutex}func(s*borrowService)BorrowBook(ctx context.Context,bookIDint,userNamestring)(*model.BorrowRecord,error){// 1. 加锁 — 防止并发超借s.mu.Lock()defers.mu.Unlock()// 2. Context 超时检查select{case-ctx.Done():returnnil,ctx.Err()default:}// 3. 检查库存book,err:s.bookRepo.GetBookByID(bookID)iferr!nil{returnnil,err}ifbook.Available0{returnnil,ErrBookNotAvailable}// 4. 扣减库存iferr:s.bookRepo.DecreaseAvailable(bookID);err!nil{returnnil,err}// 5. 创建借阅记录失败时回滚库存record,err:s.repo.AddRecord(bookID,book.Title,userName)iferr!nil{s.bookRepo.IncreaseAvailable(bookID)// 回滚returnnil,err}returnrecord,nil}设计要点Mutex 加锁同一时刻只有一个借阅操作进入临界区防止读到库存为1 → 两个请求都通过的超卖Context 超时Handler 层设置context.WithTimeout5秒超时自动取消补偿事务创建记录失败时调用IncreaseAvailable回滚库存锁粒度使用全局 Mutex简化实现v5 会升级为分布式锁main.go — 优雅关闭// 监听系统信号quit:make(chanos.Signal,1)signal.Notify(quit,syscall.SIGINT,syscall.SIGTERM)// 优雅关闭-quit fmt.Println(\n 正在关闭服务...)cancel()// 取消定时任务ctx,shutdown:context.WithTimeout(context.Background(),5*time.Second)defershutdown()srv.Shutdown(ctx)// 等待现有请求完成StartOverdueChecker — 定时任务func(s*borrowService)StartOverdueChecker(ctx context.Context){ticker:time.NewTicker(30*time.Second)gofunc(){for{select{case-ticker.C:s.checkAndUpdateOverdue()case-ctx.Done():ticker.Stop()return}}}()}三、与 v3 的对比特性v3v4业务范围仅图书管理图书借阅并发控制无Mutex Context库存模型无TotalStock/Available优雅关闭无signal Shutdown定时任务无Ticker select错误恢复middlewaremiddleware 补偿事务四、设计思想思想体现并发安全Mutex 保护共享状态防止竞态条件超时控制Context 传播取消信号防止操作阻塞补偿事务失败时回滚已执行的操作保证数据一致性优雅关闭收到信号后等待请求完成避免数据丢失定时任务Ticker select ctx.Done() 可取消的循环五、为什么需要 v5v4 实现了并发借阅但存在架构级限制单进程所有功能在一个进程中无法独立扩缩容内存存储重启丢失数据虽然会保存到文件但不适合生产全局锁Mutex 只能保护单进程内的并发多实例部署无效无缓存每次查询都从文件读取性能受限服务间强耦合BookService 和 BorrowService 在同一进程v5 的改进方向微服务拆分 MySQL 持久化 Redis 缓存/分布式锁 gRPC 通信。##六、补充内容v4 API 测试指南 一、启动服务bashcdH:/libraries-pm/go-library go run ./v4 服务启动后默认监听 http://localhost:8080 二、API 列表 方法 路径 功能 分类 POST /books 添加图书 图书管理 GET /books 查询所有图书 图书管理 GET /books/{id}查询单本图书 图书管理 PUT /books/{id}更新图书 图书管理 DELETE /books/{id}删除图书 图书管理 POST /books/save 保存到文件 图书管理 POST /books/{id}/borrow 借书 借阅管理v4新增 POST /books/{id}/return 还书 借阅管理v4新增 GET /books/{id}/status 查询图书状态 借阅管理v4新增 GET /borrows 借阅历史 借阅管理v4新增 GET /health 健康检查 系统 三、测试步骤3.1健康检查bashcurlhttp://localhost:8080/health 期望返回 json{code:0,message:success,data:{status:ok,version:v4.0}}3.2添加图书含库存bash# 添加一本库存为3的图书curl-XPOST http://localhost:8080/books\-HContent-Type: application/json\-d{title:Go并发实战,author:张三,price:69.00,stock:3}期望返回 json{code:0,message:success,data:{id:1,title:Go并发实战,author:张三,price:69,total_stock:3,available:3}}3.3查询所有图书bashcurlhttp://localhost:8080/books3.4用户A借书bashcurl-XPOST http://localhost:8080/books/1/borrow\-HContent-Type: application/json\-d{user_name:张三}期望返回库存从3变为2 json{code:0,message:success,data:{id:1,book_id:1,book_title:Go并发实战,user_name:张三,status:borrowed,...}}3.5用户B借书同一本书bashcurl-XPOST http://localhost:8080/books/1/borrow\-HContent-Type: application/json\-d{user_name:李四}3.6查询图书状态bashcurlhttp://localhost:8080/books/1/status 期望返回显示库存和借阅情况 json{code:0,message:success,data:{id:1,title:Go并发实战,total_stock:3,available:1,borrowed_count:2,borrow_records:[...]}}3.7用户A还书bashcurl-XPOST http://localhost:8080/books/1/return\-HContent-Type: application/json\-d{user_name:张三}期望返回 json{code:0,message:success,data:{message:还书成功}}3.8查询借阅历史bash# 查询某本书的借阅历史curlhttp://localhost:8080/borrows?book_id1# 查询逾期记录不传参数默认返回逾期curlhttp://localhost:8080/borrows 四、并发测试v4 核心功能4.1模拟100人抢1本书bash# 1. 先添加一本库存为1的图书curl-XPOST http://localhost:8080/books\-HContent-Type: application/json\-d{title:限量版图书,author:测试,price:99.00,stock:1}# 2. 使用脚本并发借书Linux/Macforiin{1..100};docurl-XPOST http://localhost:8080/books/2/borrow\-HContent-Type: application/json\-d{\user_name\:\user$i\}donewait# 3. 查询状态确认只有1人借到curlhttp://localhost:8080/books/2/status4.2Windows 并发测试使用 PowerShell powershell# 在 PowerShell 中执行1..100|ForEach-Object{$body{user_nameuser$_}|ConvertTo-Json Invoke-RestMethod-Urihttp://localhost:8080/books/2/borrow-MethodPOST-Body$body-ContentTypeapplication/json}|Measure-Object 五、竞态检测bash# 使用 -race 检测数据竞争gotest-race./v4/... 六、完整测试脚本bash#!/bin/bashechoecho v4 API 测试echoecho-e\n1️⃣ 健康检查curl-shttp://localhost:8080/health|jq.echo-e\n2️⃣ 添加图书库存3本curl-s-XPOST http://localhost:8080/books\-HContent-Type: application/json\-d{title:Go并发实战,author:张三,price:69.00,stock:3}|jq.echo-e\n3️⃣ 查询所有图书curl-shttp://localhost:8080/books|jq.echo-e\n4️⃣ 张三借书curl-s-XPOST http://localhost:8080/books/1/borrow\-HContent-Type: application/json\-d{user_name:张三}|jq.echo-e\n5️⃣ 李四借书curl-s-XPOST http://localhost:8080/books/1/borrow\-HContent-Type: application/json\-d{user_name:李四}|jq.echo-e\n6️⃣ 图书状态curl-shttp://localhost:8080/books/1/status|jq.echo-e\n7️⃣ 张三还书curl-s-XPOST http://localhost:8080/books/1/return\-HContent-Type: application/json\-d{user_name:张三}|jq.echo-e\n8️⃣ 再次查询状态curl-shttp://localhost:8080/books/1/status|jq.echo-e\n9️⃣ 借阅历史curl-shttp://localhost:8080/borrows?book_id1|jq.echo-e\n✅ 测试完成七、测试要点总结 测试场景 预期结果 验证方法 正常借书 库存减1生成借阅记录 查看返回数据 库存不足时借书 返回错误 库存不足 查看错误信息100人抢1本书 仅1人成功99人失败 查看状态available0正常还书 库存加1记录状态变更 查询状态 不存在的用户还书 返回错误 未找到借阅记录 查看错误信息 逾期检查 日志打印逾期记录 观察服务端日志

相关新闻

Ceph网络配置开发详解:openeuler/ceph_dev中网络架构与优化指南

Ceph网络配置开发详解:openeuler/ceph_dev中网络架构与优化指南

2026/8/26 19:57:41

Ceph网络配置开发详解:openeuler/ceph_dev中网络架构与优化指南 【免费下载链接】ceph_dev ceph_dev is a project focus on some feature developing based on ceph 项目地址: https://gitcode.com/openeuler/ceph_dev 前往项目官网免费下载:htt…

生鲜避坑农残焦虑:自有园区优势及顽虎适合谁吃

生鲜避坑农残焦虑:自有园区优势及顽虎适合谁吃

2026/8/24 10:20:58

生鲜选购避坑指南:理性看待农残焦虑与自有园区模式的价值在消费升级的大背景下,注重饮食安全的消费者在生鲜选购时,往往将核心关注点聚焦于农药残留与化学制剂的使用情况。面对市场上种类繁多的蔬菜品牌,单纯依赖外观判断已难以满…

C++双目运算符+=的重载详解

C++双目运算符+=的重载详解

2026/8/26 16:55:19

1、重载12345678910111213141516171819202122232425262728293031class Complex{public:Complex(int a, int b): _a(a), _b(b){}Complex& operator (Complex& other){this->_a other._a;this->_b other._b;return *this;}void print(){cout << _a <<…

交通信号配时优化:从静态模型到鲁棒动态系统

交通信号配时优化:从静态模型到鲁棒动态系统

2026/8/26 21:06:47

1. 这不是“改个变量名”的修修补补&#xff0c;而是对建模逻辑的重新校准2024年深圳杯与东三省数学建模联赛A题&#xff0c;核心落在“城市交通信号配时优化”这个经典但极易陷入套路的老命题上。很多参赛队交上去的代码&#xff0c;表面看跑通了、画出了热力图、输出了绿灯时…

无线充电全解析:从电磁感应原理到Qi2标准与DIY实践

无线充电全解析:从电磁感应原理到Qi2标准与DIY实践

2026/8/26 21:06:47

第一次把手机往无线充电板上一放&#xff0c;听到设备发出清脆的对位提示音&#xff0c;电量曲线开始往上走的时候&#xff0c;我就知道&#xff0c;这根线是绑不住我了。Wireless Charging 从实验室概念走到消费电子标配&#xff0c;前后不过十来年&#xff0c;现在手机、手表…

Shell脚本自动化:多步流水线与HereDoc构建高效部署流水线

Shell脚本自动化:多步流水线与HereDoc构建高效部署流水线

2026/8/26 21:06:47

1. 项目概述&#xff1a;从“手工作坊”到“智能工厂”的脚本进化如果你和我一样&#xff0c;长期和服务器、部署、数据处理打交道&#xff0c;那你一定经历过这样的场景&#xff1a;为了完成一个看似简单的任务&#xff0c;比如发布一个应用或者处理一批数据&#xff0c;你需要…

程序员高效学习技术的实战方法论与面试准备

程序员高效学习技术的实战方法论与面试准备

2026/8/26 21:06:47

1. 程序员高效学习技术的实战方法论作为一名经历过多次技术面试的老兵&#xff0c;我深知程序员在准备面试时的焦虑与困惑。2018年我从Java零基础开始&#xff0c;用三个月时间系统学习并通过了蚂蚁金服的技术面试&#xff0c;这套方法后来帮助了上百位学员成功拿到心仪offer。…

只听贝斯猜Beyond歌曲:基于Demucs的音源分离与特征匹配实战

只听贝斯猜Beyond歌曲:基于Demucs的音源分离与特征匹配实战

2026/8/26 21:06:47

如果你把一首 Beyond 的歌&#xff0c;人声、吉他、鼓全部抽掉&#xff0c;只留一条贝斯轨&#xff0c;还能听出是哪首吗&#xff1f;这个问题的技术含量并不低&#xff1a;从混音里分离贝斯&#xff0c;再把贝斯旋律映射回原曲信息&#xff0c;涉及音源分离、频谱分析、特征匹…

向量数据库与RAG实战:从Embedding到AI知识库的完整落地指南

向量数据库与RAG实战:从Embedding到AI知识库的完整落地指南

2026/8/26 20:56:46

过去在做搜索或者知识库相关功能时&#xff0c;我发现最头疼的问题不是“数据不够多”&#xff0c;而是“明明数据都在库里&#xff0c;用户就是搜不到想要的答案”。后来逐步接触到向量数据库、Embedding、RAG 这一整套技术栈&#xff0c;才慢慢把这块拼图补完整。这篇文章会从…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/26 1:50:39

首先光是一种能量的载体和形态&#xff0c;宏观上观察到的光是由无数个微观的光量子组成的&#xff0c;每个光子在产生的瞬间&#xff0c;其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前&#xff0c;在微观层面&#xff0c;每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/26 1:49:16

1. 通话转接不是“挂断再拨号”&#xff0c;而是SIP会话的动态重定向你有没有遇到过这样的场景&#xff1a;客服坐席A正在和客户通电话&#xff0c;突然需要把这通对话无缝转给专家坐席B&#xff0c;客户完全感知不到中间的断连——既没听到忙音&#xff0c;也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/26 17:50:58

1. 为什么选择Kolla-ansible来部署单节点OpenStack&#xff1f;如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法&#xff0c;那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

Python random 模块常用函数详解:从入门到实战

Python random 模块常用函数详解:从入门到实战

2026/8/26 0:05:45

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要&#xff1a; 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数&#xff08;random()、unifor…

Hermes接入团队协作后,我推翻了三个效率假设

Hermes接入团队协作后,我推翻了三个效率假设

2026/8/26 0:05:45

聊《Hermes真能提效吗&#xff1f;先看流程里最慢的那一步》之前&#xff0c;先说一句实在的&#xff1a;别急着背概念&#xff0c;先看它在真实项目里到底解决什么问题。摘要团队把 Hermes 接进项目三个月后&#xff0c;交付速度没有提升反而慢了。复盘后发现&#xff0c;最先…

免费AI大模型调教指南:打造专属网文写作助手

免费AI大模型调教指南:打造专属网文写作助手

2026/8/26 0:05:45

1. 先搞清楚“AI小说扩展模式”到底能帮你做什么如果你是一个刚开始写网文、或者卡在L3级别以下的作者&#xff0c;最头疼的可能是情节推进不下去、人物对话干瘪&#xff0c;或者世界观设定不够丰满。自己对着空白文档硬憋&#xff0c;效率很低。这时候&#xff0c;一个能理解你…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具&#xff0c;覆盖选题构思、文献整理、内容生成、格式排版等核心场景&#xff0c;真正帮你高效搞定论文难题。 一、全流程王者&#xff1a;一站式搞定论文全链路&#xff08;一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/26 18:07:30

2026年真正好用的AI论文工具&#xff0c;核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测&#xff0c;千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队&#xff0c;覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/26 17:57:52

告别游戏崩溃&#xff1a;XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…