写在最前
x. 示例项目
x. book_management
book_management/
├── main.go # 程序入口
├── book.go # 图书结构和方法
├── user.go # 用户结构和方法
├── library.go # 图书馆管理逻辑
├── storage.go # 数据存储
└── menu.go # 用户界面菜单
book.go - 图书模型
package main
import (
"fmt"
"time"
)
// Book 结构体表示一本图书
type Book struct {
ID int // 图书ID
Title string // 书名
Author string // 作者
ISBN string // ISBN号
Available bool // 是否可借
Borrower string // 借阅者姓名(如果被借出)
DueDate time.Time // 应归还日期
}
// NewBook 创建新图书
func NewBook(id int, title, author, isbn string) *Book {
return &Book{
ID: id,
Title: title,
Author: author,
ISBN: isbn,
Available: true,
Borrower: "",
DueDate: time.Time{},
}
}
// Borrow 借阅图书
func (b *Book) Borrow(borrower string, days int) error {
if !b.Available {
return fmt.Errorf("书籍《%s》已被借出", b.Title)
}
b.Available = false
b.Borrower = borrower
b.DueDate = time.Now().AddDate(0, 0, days)
return nil
}
// Return 归还图书
func (b *Book) Return() {
b.Available = true
b.Borrower = ""
b.DueDate = time.Time{}
}
// Display 显示图书信息
func (b *Book) Display() {
status := "可借阅"
if !b.Available {
status = fmt.Sprintf("已借出(借阅人:%s,应归还:%s)",
b.Borrower, b.DueDate.Format("2006-01-02"))
}
fmt.Printf("ID: %d | 《%s》- %s | ISBN: %s | 状态: %s\n",
b.ID, b.Title, b.Author, b.ISBN, status)
}user.go - 用户模型
package main
import "fmt"
// User 结构体表示系统用户
type User struct {
ID int // 用户ID
Name string // 姓名
Email string // 邮箱
Borrowed []int // 借阅的图书ID列表
}
// NewUser 创建新用户
func NewUser(id int, name, email string) *User {
return &User{
ID: id,
Name: name,
Email: email,
Borrowed: make([]int, 0),
}
}
// BorrowBook 用户借书
func (u *User) BorrowBook(bookID int) {
u.Borrowed = append(u.Borrowed, bookID)
}
// ReturnBook 用户还书
func (u *User) ReturnBook(bookID int) {
for i, id := range u.Borrowed {
if id == bookID {
u.Borrowed = append(u.Borrowed[:i], u.Borrowed[i+1:]...)
break
}
}
}
// Display 显示用户信息
func (u *User) Display() {
fmt.Printf("用户ID: %d | 姓名: %s | 邮箱: %s | 借阅数量: %d\n",
u.ID, u.Name, u.Email, len(u.Borrowed))
}storage.go - 数据存储
package main
import (
"encoding/json"
"os"
"sync"
)
// Storage 管理数据存储
type Storage struct {
Books map[int]*Book // 图书数据
Users map[int]*User // 用户数据
nextBookID int // 下一个图书ID
nextUserID int // 下一个用户ID
mu sync.RWMutex // 读写锁,保证并发安全
}
// NewStorage 创建存储实例
func NewStorage() *Storage {
return &Storage{
Books: make(map[int]*Book),
Users: make(map[int]*User),
nextBookID: 1,
nextUserID: 1,
}
}
// SaveToFile 保存数据到文件
func (s *Storage) SaveToFile(filename string) error {
s.mu.RLock()
defer s.mu.RUnlock()
data := struct {
Books map[int]*Book `json:"books"`
Users map[int]*User `json:"users"`
NextBookID int `json:"next_book_id"`
NextUserID int `json:"next_user_id"`
}{
Books: s.Books,
Users: s.Users,
NextBookID: s.nextBookID,
NextUserID: s.nextUserID,
}
file, err := json.MarshalIndent(data, "", " ")
if err != nil {
return err
}
return os.WriteFile(filename, file, 0644)
}
// LoadFromFile 从文件加载数据
func (s *Storage) LoadFromFile(filename string) error {
s.mu.Lock()
defer s.mu.Unlock()
file, err := os.ReadFile(filename)
if err != nil {
if os.IsNotExist(err) {
return nil // 文件不存在时返回nil,使用初始数据
}
return err
}
var data struct {
Books map[int]*Book `json:"books"`
Users map[int]*User `json:"users"`
NextBookID int `json:"next_book_id"`
NextUserID int `json:"next_user_id"`
}
if err := json.Unmarshal(file, &data); err != nil {
return err
}
s.Books = data.Books
s.Users = data.Users
s.nextBookID = data.NextBookID
s.nextUserID = data.NextUserID
return nil
}
// AddBook 添加图书
func (s *Storage) AddBook(title, author, isbn string) *Book {
s.mu.Lock()
defer s.mu.Unlock()
book := NewBook(s.nextBookID, title, author, isbn)
s.Books[s.nextBookID] = book
s.nextBookID++
return book
}
// AddUser 添加用户
func (s *Storage) AddUser(name, email string) *User {
s.mu.Lock()
defer s.mu.Unlock()
user := NewUser(s.nextUserID, name, email)
s.Users[s.nextUserID] = user
s.nextUserID++
return user
}
// GetBook 获取图书
func (s *Storage) GetBook(id int) (*Book, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
book, exists := s.Books[id]
return book, exists
}
// GetUser 获取用户
func (s *Storage) GetUser(id int) (*User, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
user, exists := s.Users[id]
return user, exists
}
// GetAllBooks 获取所有图书
func (s *Storage) GetAllBooks() []*Book {
s.mu.RLock()
defer s.mu.RUnlock()
books := make([]*Book, 0, len(s.Books))
for _, book := range s.Books {
books = append(books, book)
}
return books
}
// GetAllUsers 获取所有用户
func (s *Storage) GetAllUsers() []*User {
s.mu.RLock()
defer s.mu.RUnlock()
users := make([]*User, 0, len(s.Users))
for _, user := range s.Users {
users = append(users, user)
}
return users
}library.go - 核心业务逻辑
package main
import (
"fmt"
"strings"
)
// Library 图书馆管理系统
type Library struct {
storage *Storage
}
// NewLibrary 创建图书馆实例
func NewLibrary() *Library {
library := &Library{
storage: NewStorage(),
}
// 加载已有数据
if err := library.storage.LoadFromFile("library_data.json"); err != nil {
fmt.Printf("加载数据失败: %v\n", err)
fmt.Println("将使用初始空数据")
}
return library
}
// AddBook 添加图书
func (l *Library) AddBook(title, author, isbn string) {
book := l.storage.AddBook(title, author, isbn)
fmt.Printf("✅ 添加成功!图书ID: %d\n", book.ID)
l.SaveData()
}
// AddUser 添加用户
func (l *Library) AddUser(name, email string) {
user := l.storage.AddUser(name, email)
fmt.Printf("✅ 用户添加成功!用户ID: %d\n", user.ID)
l.SaveData()
}
// ListBooks 列出所有图书
func (l *Library) ListBooks() {
books := l.storage.GetAllBooks()
if len(books) == 0 {
fmt.Println("📚 图书馆暂无图书")
return
}
fmt.Printf("📚 图书列表(共 %d 本):\n", len(books))
for _, book := range books {
book.Display()
}
}
// ListUsers 列出所有用户
func (l *Library) ListUsers() {
users := l.storage.GetAllUsers()
if len(users) == 0 {
fmt.Println("👤 暂无用户")
return
}
fmt.Printf("👤 用户列表(共 %d 人):\n", len(users))
for _, user := range users {
user.Display()
}
}
// BorrowBook 借阅图书
func (l *Library) BorrowBook(bookID, userID, days int) {
book, bookExists := l.storage.GetBook(bookID)
if !bookExists {
fmt.Printf("❌ 图书ID %d 不存在\n", bookID)
return
}
user, userExists := l.storage.GetUser(userID)
if !userExists {
fmt.Printf("❌ 用户ID %d 不存在\n", userID)
return
}
if err := book.Borrow(user.Name, days); err != nil {
fmt.Printf("❌ 借阅失败: %v\n", err)
return
}
user.BorrowBook(bookID)
fmt.Println("✅ 借阅成功!")
l.SaveData()
}
// ReturnBook 归还图书
func (l *Library) ReturnBook(bookID int) {
book, exists := l.storage.GetBook(bookID)
if !exists {
fmt.Printf("❌ 图书ID %d 不存在\n", bookID)
return
}
if book.Available {
fmt.Println("❌ 这本书没有被借出")
return
}
// 找到借阅者并更新其借阅记录
for _, user := range l.storage.GetAllUsers() {
for _, borrowedID := range user.Borrowed {
if borrowedID == bookID {
user.ReturnBook(bookID)
break
}
}
}
book.Return()
fmt.Println("✅ 归还成功!")
l.SaveData()
}
// SearchBooks 搜索图书
func (l *Library) SearchBooks(keyword string) {
books := l.storage.GetAllBooks()
results := make([]*Book, 0)
keyword = strings.ToLower(keyword)
for _, book := range books {
if strings.Contains(strings.ToLower(book.Title), keyword) ||
strings.Contains(strings.ToLower(book.Author), keyword) ||
strings.Contains(strings.ToLower(book.ISBN), keyword) {
results = append(results, book)
}
}
if len(results) == 0 {
fmt.Printf("🔍 未找到包含 \"%s\" 的图书\n", keyword)
return
}
fmt.Printf("🔍 找到 %d 本相关图书:\n", len(results))
for _, book := range results {
book.Display()
}
}
// SaveData 保存数据
func (l *Library) SaveData() {
if err := l.storage.SaveToFile("library_data.json"); err != nil {
fmt.Printf("⚠️ 保存数据失败: %v\n", err)
} else {
fmt.Println("💾 数据已自动保存")
}
}menu.go - 用户界面
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// Menu 管理用户界面
type Menu struct {
library *Library
scanner *bufio.Scanner
}
// NewMenu 创建菜单
func NewMenu(library *Library) *Menu {
return &Menu{
library: library,
scanner: bufio.NewScanner(os.Stdin),
}
}
// Run 运行主菜单
func (m *Menu) Run() {
for {
m.showMainMenu()
choice := m.getInput("请选择操作: ")
switch choice {
case "1":
m.addBook()
case "2":
m.library.ListBooks()
case "3":
m.addUser()
case "4":
m.library.ListUsers()
case "5":
m.borrowBook()
case "6":
m.returnBook()
case "7":
m.searchBooks()
case "8":
fmt.Println("谢谢使用!再见!")
m.library.SaveData()
return
default:
fmt.Println("无效选择,请重新输入")
}
fmt.Println()
}
}
func (m *Menu) showMainMenu() {
fmt.Println("\n===== 图书管理系统 =====")
fmt.Println("1. 添加图书")
fmt.Println("2. 查看所有图书")
fmt.Println("3. 添加用户")
fmt.Println("4. 查看所有用户")
fmt.Println("5. 借阅图书")
fmt.Println("6. 归还图书")
fmt.Println("7. 搜索图书")
fmt.Println("8. 退出系统")
fmt.Println("======================")
}
func (m *Menu) addBook() {
fmt.Println("\n--- 添加图书 ---")
title := m.getInput("书名: ")
author := m.getInput("作者: ")
isbn := m.getInput("ISBN: ")
if title == "" || author == "" {
fmt.Println("❌ 书名和作者不能为空")
return
}
m.library.AddBook(title, author, isbn)
}
func (m *Menu) addUser() {
fmt.Println("\n--- 添加用户 ---")
name := m.getInput("姓名: ")
email := m.getInput("邮箱: ")
if name == "" {
fmt.Println("❌ 姓名不能为空")
return
}
m.library.AddUser(name, email)
}
func (m *Menu) borrowBook() {
fmt.Println("\n--- 借阅图书 ---")
bookIDStr := m.getInput("图书ID: ")
bookID, err := strconv.Atoi(bookIDStr)
if err != nil {
fmt.Println("❌ 请输入有效的图书ID(数字)")
return
}
userIDStr := m.getInput("用户ID: ")
userID, err := strconv.Atoi(userIDStr)
if err != nil {
fmt.Println("❌ 请输入有效的用户ID(数字)")
return
}
daysStr := m.getInput("借阅天数: ")
days, err := strconv.Atoi(daysStr)
if err != nil || days <= 0 {
fmt.Println("❌ 请输入有效的借阅天数(正整数)")
return
}
m.library.BorrowBook(bookID, userID, days)
}
func (m *Menu) returnBook() {
fmt.Println("\n--- 归还图书 ---")
bookIDStr := m.getInput("图书ID: ")
bookID, err := strconv.Atoi(bookIDStr)
if err != nil {
fmt.Println("❌ 请输入有效的图书ID(数字)")
return
}
m.library.ReturnBook(bookID)
}
func (m *Menu) searchBooks() {
fmt.Println("\n--- 搜索图书 ---")
keyword := m.getInput("请输入书名、作者或ISBN关键字: ")
if keyword == "" {
fmt.Println("❌ 搜索关键字不能为空")
return
}
m.library.SearchBooks(keyword)
}
func (m *Menu) getInput(prompt string) string {
fmt.Print(prompt)
m.scanner.Scan()
return strings.TrimSpace(m.scanner.Text())
}main.go - 程序入口
package main
import "fmt"
func main() {
fmt.Println("📚 欢迎使用图书管理系统")
fmt.Println("========================")
// 初始化图书馆系统
library := NewLibrary()
// 初始化菜单
menu := NewMenu(library)
// 运行系统
menu.Run()
}
评论