news 2026/7/3 4:17:06

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
go语言项目--实例化(图书管理)--001

案例1:图书管理系统golang

一、项目概述

项目名称:图书管理系统

当前版本:v1.0 - 图书管理系统golang

业务功能:交互式命令行录入图书信息,保存到books.txt

学习目标

  • Go基础语法(变量、常量、类型)

  • 流程控制(if/else、for循环、break)

  • 函数定义与多返回值

  • 错误处理(error接口)

  • 文件操作(os.Create、bufio.Writer)

  • 字符串处理(strings.TrimSpace、strconv.ParseFloat)

运行方式go run main.go

二、完整代码

文件路径case1/main.go

go

复制

下载

// ============================================================ // 图书管理系统 v1.0 - 图书录入器 // 功能:交互式命令行录入图书信息,保存到 books.txt // 学习目标:基础语法、流程控制、函数、错误处理、文件操作 // 运行方式:go run main.go // ============================================================ package main import ( "bufio" "fmt" "os" "strconv" "strings" ) // ============================================================ // 常量定义 // ============================================================ const ( dataFile = "books.txt" // 数据文件名 exitCmd = "quit" // 退出命令 ) // ============================================================ // 主函数 - 程序入口 // ============================================================ func main() { printWelcome() // 打开文件(追加模式) file, err := os.OpenFile(dataFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { fmt.Printf("❌ 打开文件失败: %v\n", err) return } defer file.Close() writer := bufio.NewWriter(file) defer writer.Flush() scanner := bufio.NewScanner(os.Stdin) count := 0 // 主循环 for { fmt.Print("\n📖 请输入(书名,作者,价格),输入 quit 退出: ") scanner.Scan() input := strings.TrimSpace(scanner.Text()) if input == exitCmd { fmt.Printf("\n✅ 共录入 %d 本图书,已保存到 %s\n", count, dataFile) break } // 解析输入 title, author, priceStr, err := parseInput(input) if err != nil { fmt.Printf("❌ 格式错误: %v(正确格式:书名,作者,价格)\n", err) continue } // 校验 if err := validateTitle(title); err != nil { fmt.Printf("❌ %v\n", err) continue } if err := validateAuthor(author); err != nil { fmt.Printf("❌ %v\n", err) continue } price, err := parsePrice(priceStr) if err != nil { fmt.Printf("❌ %v\n", err) continue } // 写入文件 line := fmt.Sprintf("%s,%s,%.2f\n", title, author, price) if _, err := writer.WriteString(line); err != nil { fmt.Printf("❌ 写入失败: %v\n", err) continue } writer.Flush() count++ fmt.Printf("✅ 第 %d 本录入成功: %s\n", count, strings.TrimSpace(line)) } } // ============================================================ // 辅助函数 // ============================================================ func printWelcome() { fmt.Println("========================================") fmt.Println(" 📚 图书管理系统 v1.0 - 图书录入器") fmt.Println("========================================") fmt.Printf(" 💡 格式:书名,作者,价格\n") fmt.Printf(" 💡 输入 %s 退出\n", exitCmd) fmt.Printf(" 💡 数据保存到 %s\n", dataFile) fmt.Println("========================================") } // parseInput 按逗号分割输入,返回书名、作者、价格字符串 func parseInput(input string) (title, author, price string, err error) { parts := strings.Split(input, ",") if len(parts) != 3 { return "", "", "", fmt.Errorf("需要3个字段,实际%d个", len(parts)) } return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2]), nil } // validateTitle 校验书名不能为空 func validateTitle(title string) error { if title == "" { return fmt.Errorf("书名不能为空") } return nil } // validateAuthor 校验作者不能为空 func validateAuthor(author string) error { if author == "" { return fmt.Errorf("作者不能为空") } return nil } // parsePrice 解析价格,必须为数字且 >= 0 func parsePrice(priceStr string) (float64, error) { price, err := strconv.ParseFloat(priceStr, 64) if err != nil { return 0, fmt.Errorf("价格格式错误") } if price < 0 { return 0, fmt.Errorf("价格不能为负数") } return price, nil } // ============================================================ // 备选交互方式:fmt.Scanln(注释掉,供参考对比) // 优点:写法简洁;缺点:无法处理带空格的输入 // ============================================================ // var title, author, priceStr string // fmt.Print("请输入书名: ") // fmt.Scanln(&title) // fmt.Print("请输入作者: ") // fmt.Scanln(&author) // fmt.Print("请输入价格: ") // fmt.Scanln(&priceStr) // ============================================================ // 本案例知识点: // 变量/常量 | if/for | 函数多返回值 | error处理 | 文件操作 | 字符串处理 // ============================================================

三、测试代码(精简版)

文件路径case1/main_test.go

go

复制

下载

package main import "testing" // 测试价格解析 func TestParsePrice(t *testing.T) { tests := []struct { name string input string want float64 ok bool // true表示期望成功 }{ {"正常价格", "59.00", 59.00, true}, {"整数", "59", 59.00, true}, {"零元", "0", 0, true}, {"负数", "-10", 0, false}, {"非数字", "abc", 0, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := parsePrice(tt.input) if tt.ok && err != nil { t.Errorf("期望成功,但返回错误: %v", err) } if !tt.ok && err == nil { t.Errorf("期望失败,但成功了") } if tt.ok && got != tt.want { t.Errorf("got %f, want %f", got, tt.want) } }) } } // 测试书名校验 func TestValidateTitle(t *testing.T) { err := validateTitle("") if err == nil { t.Error("空书名应该返回错误") } err = validateTitle("Go语言") if err != nil { t.Errorf("正常书名不应该返回错误: %v", err) } } // 测试输入解析 func TestParseInput(t *testing.T) { title, author, price, err := parseInput("Go语言,张三,59.00") if err != nil { t.Errorf("解析失败: %v", err) } if title != "Go语言" || author != "张三" || price != "59.00" { t.Errorf("解析结果不符: %s, %s, %s", title, author, price) } _, _, _, err = parseInput("Go语言,张三") if err == nil { t.Error("字段不足应该返回错误") } } // 运行测试:go test -v // 运行指定测试:go test -v -run TestParsePrice

四、运行指南

bash

复制

下载

# 运行程序 cd case1 go run main.go # 运行测试 go test -v # 测试覆盖率 go test -v -cover

五、交互示例

text

复制

下载

======================================== 📚 图书管理系统 v1.0 - 图书录入器 ======================================== 💡 格式:书名,作者,价格 💡 输入 quit 退出 💡 数据保存到 books.txt ======================================== 📖 请输入(书名,作者,价格),输入 quit 退出: Go语言实战,张三,59.00 ✅ 第 1 本录入成功: Go语言实战,张三,59.00 📖 请输入(书名,作者,价格),输入 quit 退出: ,王五,30 ❌ 书名不能为空 📖 请输入(书名,作者,价格),输入 quit 退出: 测试书,赵六,-10 ❌ 价格不能为负数 📖 请输入(书名,作者,价格),输入 quit 退出: quit ✅ 共录入 1 本图书,已保存到 books.txt

六、案例1 → 案例2 衔接

text

复制

下载

============================================================ 📌 案例1结束,案例2衔接说明 ============================================================ 1. 本案例已学知识点: ✅ 变量/常量、基本类型 ✅ if/else、for循环、break ✅ 函数定义与多返回值 ✅ error错误处理 ✅ 文件操作(os.OpenFile、defer) ✅ 缓冲写入(bufio.Writer) ✅ 字符串处理(TrimSpace、Split) ✅ 类型转换(strconv.ParseFloat) ✅ 单元测试(表驱动测试、t.Run) 2. 案例2将升级: 📄 books.txt → books.json(结构化数据) 📁 单文件 → 多包分层(model/repository/handler) 🔧 仅录入 → 完整CRUD(增删改查) 3. 本案例后续可优化(将在案例2中实现): 🔸 用结构体代替分散的字符串变量 🔸 用JSON替代纯文本,支持结构化存储 🔸 增加查询、更新、删除功能 🔸 增加内存存储,提高操作效率 ============================================================
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/3 4:16:02

高效的许可证管理体系如何打造?行业领先者经验分享

去年秋天&#xff0c;我接到一个老客户的紧急求助电话。电话那头是某大型装备制造企业的IT经理张经理&#xff0c;他听起来相当焦虑。事情是这样的&#xff0c;他们公司刚完成一轮新产品的研发冲刺&#xff0c;财务部门在做季度成本复盘时突然发现&#xff0c;软件采购支出比预…

作者头像 李华
网站建设 2026/7/3 4:14:31

微服务架构的权衡:优势、劣势与单体架构对比

许多开发团队认为&#xff0c;微服务架构优于单体架构&#xff1b;也有一些团队认为&#xff0c;微服务反而会降低生产力。和任何架构风格一样&#xff0c;微服务既有优势&#xff0c;也有劣势。要做出明智选择&#xff0c;就必须充分理解这些利弊&#xff0c;并结合具体场景进…

作者头像 李华
网站建设 2026/7/3 4:01:46

数据整合难?2026年GIS三维软件公司推荐,解决你的协同难题

摘要 本文基于公开可查的工商信息及企业官方发布资料&#xff0c;对当前三维地理信息软件行业的产品方案进行分析。聚焦测绘资质配置中的软件组合问题&#xff0c;梳理现有解决方案中常见的配置需求与技术特点&#xff0c;供行业从业者在实际业务选型时参考。 一、三维数据处理…

作者头像 李华
网站建设 2026/7/3 4:01:34

如何利用软件计算流域面积(Global Mapeer)

流域面积&#xff08;集水面积 F&#xff09;&#xff1a;地表水能够汇集到某一出口断面&#xff08;水库坝址、河道断面&#xff09;的全部区域的水平投影面积&#xff0c;单位常用&#xff1a;km&#xff08;下雨后&#xff0c;这片区域所有雨水&#xff0c;顺着地形、山沟、…

作者头像 李华
网站建设 2026/7/3 4:00:26

2026年QMS质量管理系统选型指南:趋势、评分标准、厂商对比及避坑攻略

前言2026年制造业QMS选型逻辑已发生根本性变革&#xff0c;彻底告别只看功能多少的传统模式。当下核心选型逻辑聚焦四大核心维度&#xff1a;行业合规适配、现有IT系统集成、TCO总成本可控、业务灵活迭代。同时&#xff0c;国产替代加速、低代码/云SaaS普及、IATF16949合规刚需…

作者头像 李华
网站建设 2026/7/3 4:00:08

助睿实验选做-数据抽取-使用助睿ETL抽取多种文件数据

助睿实验选做&#xff1a;数据抽取——使用助睿ETL抽取多种文件数据 一、实验背景 1.1 实验目的 本次实验旨在通过助睿数智&#xff08;Uniplore&#xff09;平台的 ETL 数据集成模块&#xff0c;掌握多种文件格式数据的抽取与基本加工方法&#xff0c;具体包括&#xff1a;…

作者头像 李华