Golang小项目(3)
Golang 小项目(3)
前言
本项目适合 Golang 初学者,通过简单的项目实践来加深对 Golang 的基本语法和 Web 开发的理解。
项目文件已上传至 https://github.com/Done-0/go-bookstore
项目结构
D:.
├─ go.mod
├─ go.sum
│
├─cmd
│ └─main
│ main.go
│
└─pkg
├─config
│ app.go
│
├─controllers
│ book-controller.go
│
├─models
│ book.go
│
├─routes
│ bookstore-routes.go
│
└─utils
utils.go
项目流程图
- 技术栈
- 项目结构
- 项目路由
项目初始化
- 初始化项目文件夹
mkdir go-bookstore
cd go-bookstore
- 初始化
mod
文件
cd go-bookstore
go mod init github.com/your_username/go-bookstore
注意,此处的
your_username
请替换为你的 GitHub 用户名
- 安装依赖包
# GORM 是一个用于 Go 的 ORM(对象关系映射)库,可以简化与数据库的交互。
go get "github.com/jinzhu/gorm"
# 这个包提供了与 MySQL 数据库的连接和操作功能,使得可以使用 GORM 进行 MySQL 数据库的 CRUD 操作。
go get "github.com/jinzhu/gorm/dialects/mysql"
# Gorilla Mux 是一个强大的 HTTP 路由和调度库,可以处理请求路由,支持路径变量、查询参数等功能。
go get "github.com/gorilla/mux"
# 打开 VSCode 编辑器
code .
- 创建
go-bookstore
数据库
打开
Mysql
客户端,输入以下命令创建go-bookstore
数据库:
CREATE DATABASE `database_name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
其中,
database_name
请替换为你自己喜欢的数据库名称。
- 初始化项目结构
一行代码在项目根目录下创建目录和空文件
# windows系统
mkdir cmd\main pkg\config pkg\controllers pkg\models pkg\routes pkg\utils & type nul > cmd\main\main.go & type nul > pkg\config\app.go & type nul > pkg\controllers\book-controller.go & type nul > pkg\models\book.go & type nul > pkg\routes\bookstore-routes.go & type nul > pkg\utils\utils.go
# Linux/mac系统
mkdir -p cmd/main pkg/config pkg/controllers pkg/models pkg/routes pkg/utils && touch cmd/main/main.go pkg/config/app.go pkg/controllers/book-controller.go pkg/models/book.go pkg/routes/bookstore-routes.go pkg/utils/utils.go
项目编写
- 编写
pkg/routes/bookstore-routes.go
文件
package routes
import (
// 引入路由库 Gorilla Mux
"github.com/gorilla/mux"
// 引入 controllers 包: 定义控制器代码的包,比如处理 HTTP 请求
"github.com/yourname/go-bookstore/pkg/controllers"
// 声明变量RegisterBookStoreRoutes,这种方式允许你将函数赋值给变量,然后通过这个变量来调用函数。
// func() 是一个匿名函数(或称为闭包),它接受一个参数 router,这个参数是 *mux.Router 类型。
// mux.Router 是来自 Gorilla Mux 包的一个类型,用于处理路由和请求。
var RegisterBookStoreRoutes = func(router *mux.Router) {
// 将 /book/ 路径和 POST 方法映射到 controllers.CreateBook 函数。
// 也就是说,当一个 POST 请求发送到 /book/ 时,controllers.CreateBook 函数将被调用来处理这个请求。
router.HandleFunc("/book/", controllers.CreateBook).Methods("POST")
router.HandleFunc("/book/", controllers.GetBook).Methods("GET")
router.HandleFunc("/book/{BookId}", controllers.GetBookById).Methods("GET")
router.HandleFunc("/book/{BookId}", controllers.UpdateBook).Methods("PUT")
router.HandleFunc("/book/{BookId}", controllers.DeleteBook).Methods("DELETE")
}
)
注意,此处的
yourusername
请替换为你的 GitHub 用户名。
- 编写
pkg/config/app.go
文件
package config
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
var (
db * gorm.DB
)
func Connect() {
// 其中root对应你的数据库用户名,yourpassword对应你的数据库密码,database_name对应你的数据库名称。
d, err := gorm.Open("mysql", "root:your_password@tcp(127.0.0.1:3306)/database_name?chartset=utf8&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
fmt.Println("Connect to database successfully")
db = d
}
func GetDB() *gorm.DB {
return db
}
注意,此处的
your_password
请替换为你的数据库密码。
- 编写
pkg/utils/utils.go
文件
package utils
import (
"encoding/json"
"io"
"net/http"
)
// ParseBody 从 HTTP 请求中读取 JSON 数据并解析到指定的接口中
func ParseBody(r *http.Request, x interface{}) {
// 读取请求体
if body, err := io.ReadAll(r.Body); err == nil {
// 解析 JSON 数据
if err := json.Unmarshal([]byte(body), x); err != nil {
return
}
}
}
- 编写
pkg/models/models.go
文件
package models
import (
"github.com/jinzhu/gorm"
"github.com/Done-0/go-bookstore/pkg/config"
)
var db *gorm.DB
type Book struct {
// 嵌套 gorm.Model 结构体,它包含了默认的字段:ID(主键)、CreatedAt、UpdatedAt 和 DeletedAt(软删除)。
gorm.Model
Name string `json:"name"`
Author string `json:"author"`
Publication string `json:"publication"`
}
// init 函数是 Go 语言中的特殊函数,它会在包初始化时自动执行。通常用来做一些初始化操作,如设置数据库连接、初始化配置等。
func init() {
config.Connect()
db = config.GetDB()
// 使用 GORM 的 AutoMigrate 方法自动迁移 Book 结构体。
// 自动迁移会创建或更新数据库表,使其与 Book 结构体匹配。如果表不存在,则创建表;如果表已存在,则更新表结构以匹配 Book 结构体的定义。
db.AutoMigrate(&Book{})
}
// CreateBook 方法用于创建 Book 结构体的实例并插入到数据库中。
func (b *Book) CreateBook() *Book{
db.NewRecord(b)
db.Create(&b)
return b
}
// GetAllBooks 方法用于从数据库中获取所有 Book 结构体的实例。
func GetAllBooks() []Book {
var Books []Book
db.Find(&Books)
return Books
}
// GetBookById 方法用于从数据库中获取指定 ID 的 Book 结构体的实例。
func GetBookById(Id int64) (*Book, *gorm.DB) {
var getBook Book
db:=db.Where("ID=?", Id).Find(&getBook)
return &getBook, db
}
// DeleteBook 方法用于从数据库中删除指定 ID 的 Book 结构体的实例。
func DeleteBook(ID int64) Book {
var book Book
db.Where("ID=?", ID).Delete(book)
return book
}
- 编写
cmd/main/main.go
文件
package main
import (
"log"
"net/http"
"github.com/gorilla/mux"
_ "github.com/jinzhu/gorm/dialects/mysql"
"github.com/Done-0/go-bookstore/pkg/routes"
)
func main() {
// 创建一个新的路由器实例。
r := mux.NewRouter()
// 注册路由规则到路由器实例中。
routes.RegisterBookStoreRoutes(r)
// 设置路由器处理所有根路径的 HTTP 请求。
http.Handle("/", r)
// 启动 HTTP 服务器,并监听 localhost:9010 地址上的请求。若启动失败,记录错误信息并终止程序。
log.Fatal(http.ListenAndServe("localhost:9010", r))
}
- 编写
pkg/controllers/book-controller.go
文件
package controllers
import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"net/http"
"strconv"
"github.com/Done-0/go-bookstore/pkg/utils"
"github.com/Done-0/go-bookstore/pkg/models"
)
var NewBook models.Book
func GetBook(w http.ResponseWriter, r *http.Request) {
newBooks := models.GetAllBooks()
// 将newBooks 数据结构编码为 JSON 格式。json.Marshal 函数返回两个值,第一个是 JSON 编码后的字节切片 res,第二个是错误信息(如果有的话)。
res, _ := json.Marshal(newBooks)
// 设置响应头 Content-Type 为 application/json,告知客户端响应内容是 JSON 格式。
w.Header().Set("Content-Type", "pkglication/json")
// 设置 HTTP 响应的状态码为 200(OK),表示请求成功且响应内容正常。
w.WriteHeader(http.StatusOK)
// 将 JSON 编码后的数据 res 写入响应体,发送给客户端。
w.Write(res)
}
// GetBookById 根据书籍ID获取书籍详情
// 通过URL路径参数获取书籍ID,然后调用models包中的GetBookById函数获取书籍详情,
// 最后将书籍详情以JSON格式返回给客户端。
func GetBookById(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
bookId := vars["bookId"]
ID, err := strconv.ParseInt(bookId,0,0)
if err != nil {
fmt.Println("error write parsing")
}
bookDetails, _ := models.GetBookById(ID)
res, _ := json.Marshal(bookDetails)
w.Header().Set("Content-Type", "pkglication/json")
w.WriteHeader(http.StatusOK)
w.Write(res)
}
// CreateBook 创建新的书籍记录
// 解析请求体中的书籍信息,然后调用models包中的CreateBook方法创建新的书籍记录,
// 最后将创建结果以JSON格式返回给客户端。
// 注意:这里假设models.Book结构体有一个CreateBook()方法来处理创建逻辑。
func CreateBook(w http.ResponseWriter, r *http.Request) {
CreateBook := &models.Book{}
utils.ParseBody(r, CreateBook)
b := CreateBook.CreateBook()
res, _ := json.Marshal(b)
w.Header().Set("Content-Type", "pkglication/json")
w.WriteHeader(http.StatusOK)
w.Write(res)
}
// DeleteBook 根据书籍ID删除书籍记录
// 通过URL路径参数获取书籍ID,然后调用models包中的DeleteBook函数删除书籍记录,
// 最后将删除结果以JSON格式返回给客户端。
func DeleteBook(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
bookId := vars["bookId"]
ID, err := strconv.ParseInt(bookId,0,0)
if err != nil {
fmt.Printf("error while parsing")
}
book := models.DeleteBook(ID)
res, _ := json.Marshal(book)
w.Header().Set("Content-Type", "pkglication/json")
w.WriteHeader(http.StatusOK)
w.Write(res)
}
// UpdateBook 更新书籍信息
// 解析请求体中的书籍信息,然后结合URL路径参数中的书籍ID,调用models包中的相关方法更新书籍记录,
// 最后将更新后的书籍详情以JSON格式返回给客户端。
func UpdateBook(w http.ResponseWriter, r *http.Request) {
var updateBook = &models.Book{}
utils.ParseBody(r, updateBook)
vars := mux.Vars(r)
bookId := vars["bookId"]
ID, err := strconv.ParseInt(bookId,0,0)
if err != nil {
fmt.Println("error while parsing")
}
bookDetails, db := models.GetBookById(ID)
if updateBook.Name != "" {
bookDetails.Name = updateBook.Name
}
if updateBook.Author != "" {
bookDetails.Author = updateBook.Author
}
if updateBook.Publication != "" {
bookDetails.Publication = updateBook.Publication
}
db.Save(&bookDetails)
res, _ := json.Marshal(bookDetails)
w.Header().Set("Content-Type","pkglication/json")
w.WriteHeader(http.StatusOK)
w.Write(res)
}
运行项目
- 编译项目
go run cmd/main/main.go
postman
测试
进入Postman测试接口,验证项目功能是否正常:
GET ALL
接口地址:http://localhost:9010/book/
GET BY ID
接口地址:http://localhost:9010/book/1
CREATE
接口地址:http://localhost:9010/book/
UPDATE
接口地址:http://localhost:9010/book/1
DELETE
接口地址:http://localhost:9010/book/1
书籍创建之
JSON
模板:
{
"ID": 1,
"createdAt": "2024-08-29T13:26:00Z",
"updatedAt": "2024-08-29T13:26:00Z",
"DeleteAt": null,
"name": "Go 语言",
"author": "老子",
"publication": "人民邮电出版社",
}
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Fender