在学习 Go 的过程中,很多同学会做一些小型实战项目来加深理解。本篇带来的案例是一个图书管理系统 ,它采用 文件存储 的方式保存数据(JSON 文件),避免了引入数据库的复杂度,非常适合作为入门级的项目实践。
一、项目目标
我们要实现一个简易的命令行版 图书管理系统,功能如下:
- ✅ 添加图书(标题、作者、价格)
- ✅ 删除图书(根据 ID)
- ✅ 查询图书(按 ID 或标题模糊搜索)
- ✅ 列出所有图书
- ✅ 数据持久化(保存到 JSON 文件,程序退出后数据不丢失)
二、系统设计
数据结构:
go
type Book struct {
ID int `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
- 每本书有唯一 ID
- 图书列表存放在一个
[]Book
中 - 数据通过 JSON 序列化存储到
books.json
模块划分:
- 数据持久化层:负责加载和保存 JSON 文件
- 业务逻辑层:增删改查操作
- 命令行交互层:菜单驱动
三、完整代码示例
go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
)
// Book 图书结构体
type Book struct {
ID int `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
// 全局图书切片
var books []Book
var dataFile = "books.json"
// 加载图书数据
func loadBooks() {
file, err := ioutil.ReadFile(dataFile)
if err != nil {
if os.IsNotExist(err) {
books = []Book{}
return
}
fmt.Println("加载数据失败:", err)
return
}
_ = json.Unmarshal(file, &books)
}
// 保存图书数据
func saveBooks() {
data, err := json.MarshalIndent(books, "", " ")
if err != nil {
fmt.Println("保存数据失败:", err)
return
}
_ = ioutil.WriteFile(dataFile, data, 0644)
}
// 添加图书
func addBook(title, author string, price float64) {
id := 1
if len(books) > 0 {
id = books[len(books)-1].ID + 1
}
book := Book{ID: id, Title: title, Author: author, Price: price}
books = append(books, book)
saveBooks()
fmt.Println("✅ 图书添加成功:", book)
}
// 删除图书
func deleteBook(id int) {
index := -1
for i, b := range books {
if b.ID == id {
index = i
break
}
}
if index == -1 {
fmt.Println("❌ 未找到该 ID 的图书")
return
}
books = append(books[:index], books[index+1:]...)
saveBooks()
fmt.Println("✅ 图书删除成功")
}
// 查询图书
func searchBook(keyword string) {
keyword = strings.ToLower(keyword)
found := false
for _, b := range books {
if strings.Contains(strings.ToLower(b.Title), keyword) || fmt.Sprintf("%d", b.ID) == keyword {
fmt.Printf("📖 ID:%d | 标题:%s | 作者:%s | 价格:%.2f\n", b.ID, b.Title, b.Author, b.Price)
found = true
}
}
if !found {
fmt.Println("🔍 未找到匹配的图书")
}
}
// 列出所有图书
func listBooks() {
if len(books) == 0 {
fmt.Println("暂无图书")
return
}
fmt.Println("📚 图书列表:")
for _, b := range books {
fmt.Printf("ID:%d | 标题:%s | 作者:%s | 价格:%.2f\n", b.ID, b.Title, b.Author, b.Price)
}
}
// 主菜单
func main() {
loadBooks()
for {
fmt.Println("\n==== 图书管理系统 ====")
fmt.Println("1. 添加图书")
fmt.Println("2. 删除图书")
fmt.Println("3. 查询图书")
fmt.Println("4. 列出所有图书")
fmt.Println("5. 退出")
fmt.Print("请输入选项: ")
var choice int
fmt.Scanln(&choice)
switch choice {
case 1:
var title, author string
var price float64
fmt.Print("输入标题: ")
fmt.Scanln(&title)
fmt.Print("输入作者: ")
fmt.Scanln(&author)
fmt.Print("输入价格: ")
fmt.Scanln(&price)
addBook(title, author, price)
case 2:
var id int
fmt.Print("输入要删除的图书ID: ")
fmt.Scanln(&id)
deleteBook(id)
case 3:
var keyword string
fmt.Print("输入图书ID或标题关键字: ")
fmt.Scanln(&keyword)
searchBook(keyword)
case 4:
listBooks()
case 5:
fmt.Println("退出系统,再见!👋")
return
default:
fmt.Println("无效选项,请重新输入")
}
}
}
四、运行效果
bash
$ go run main.go
==== 图书管理系统 ====
1. 添加图书
2. 删除图书
3. 查询图书
4. 列出所有图书
5. 退出
请输入选项: 1
输入标题: Go语言实战
输入作者: 张三
输入价格: 59.9
✅ 图书添加成功: {1 Go语言实战 张三 59.9}
再次运行,可以看到数据被保存到 books.json
,实现了持久化。
五、总结与扩展
这个简易的图书管理系统涵盖了文件读写、JSON 序列化、数据结构操作、命令行交互等知识点,是 Go 入门的非常好的练手项目。