bookManager
项目结构
contraller目录存放相关业务的处理函数 dao目录存放数据库相关 middleware存放中间件 model存放模型 router存放路由 main.go项目入口
├── Readme.md
├── contraller
│ ├── book.go
│ └── user.go
├── dao
│ └── mysql
│ └── mysql.go
├── go.mod
├── go.sum
├── main.go
├── middleware
│ └── auth.go
├── model
│ ├── book.go
│ ├── user.go
│ └── user_m2m_book.go
└── router
├── api_router.go
├── init_router.go
└── test_router.go
contraller
book.go
处理book相关操作的函数
package contraller
import (
"bookManage/dao/mysql"
"bookManage/model"
"github.com/gin-gonic/gin"
"strconv"
)
func CreateBookHandler ( c * gin. Context) {
p := new ( model. Book)
if err := c. ShouldBind ( p) ; err != nil {
c. JSON ( 400 , gin. H{ "error" : err. Error ( ) } )
return
}
mysql. DB. Create ( p)
c. JSON ( 200 , gin. H{ "msg" : "success" } )
}
func GetBookListHandler ( c * gin. Context) {
books := [ ] model. Book{ }
mysql. DB. Preload ( "Users" ) . Find ( & books)
c. JSON ( 200 , gin. H{ "books" : books} )
}
func GetBookDetailHandler ( c * gin. Context) {
idStr := c. Param ( "id" )
bookId, _ := strconv. ParseInt ( idStr, 10 , 64 )
book := model. Book{ Id: bookId}
mysql. DB. Find ( & book)
c. JSON ( 200 , gin. H{ "books" : book} )
}
func UpdateBookHandler ( c * gin. Context) {
p := new ( model. Book)
if err := c. ShouldBindJSON ( p) ; err != nil {
c. JSON ( 400 , gin. H{ "error" : err. Error ( ) } )
return
}
oldBook := & model. Book{ Id: p. Id}
var newBook model. Book
if p. Name != "" {
newBook. Name = p. Name
}
if p. Desc != "" {
newBook. Desc = p. Desc
}
mysql. DB. Model ( & oldBook) . Updates ( newBook)
c. JSON ( 200 , gin. H{ "book" : newBook} )
}
func DeleteBookHandler ( c * gin. Context) {
idStr := c. Param ( "id" )
bookId, _ := strconv. ParseInt ( idStr, 10 , 64 )
mysql. DB. Select ( "Users" ) . Delete ( & model. Book{ Id: bookId} )
c. JSON ( 200 , gin. H{ "msg" : "success" } )
}
user.go
处理用户登陆相关的函数
package contraller
import (
"bookManage/dao/mysql"
"bookManage/model"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
func RegisterHandler ( c * gin. Context) {
p := new ( model. User)
if err := c. ShouldBind ( p) ; err != nil {
c. JSON ( 400 , gin. H{ "err" : err. Error ( ) } )
return
}
mysql. DB. Create ( p)
c. JSON ( 200 , gin. H{ "msg" : p} )
}
func LoginHandler ( c * gin. Context) {
p := new ( model. User)
if err := c. ShouldBind ( p) ; err != nil {
c. JSON ( 403 , gin. H{ "err" : err. Error ( ) } )
}
u := model. User{ Username: p. Username, Password: p. Password}
if rows := mysql. DB. Where ( & u) . First ( & u) . Row ( ) ; rows == nil {
c. JSON ( 403 , gin. H{ "msg" : "error username or password" } )
return
}
token := uuid. New ( ) . String ( )
mysql. DB. Model ( u) . Update ( "token" , token)
c. JSON ( 200 , gin. H{ "token" : token} )
}
dao
mysql
mysql.go
mysql连接相关的函数
package mysql
import (
"bookManage/model"
"fmt"
gmysql "gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB * gorm. DB
func InitMysql ( ) {
dsn := "root:123456@tcp(127.0.0.1:3306)/books?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm. Open ( gmysql. Open ( dsn) , & gorm. Config{ } )
if err != nil {
fmt. Println ( "初始化mysql连接错误" , err)
}
DB = db
if err := DB. AutoMigrate ( model. User{ } , model. Book{ } ) ; err != nil {
fmt. Println ( "自动创建表结构失败:" , err)
}
}
middleware
auth.go
认证相关的函数
package middleware
import (
"bookManage/dao/mysql"
"bookManage/model"
"github.com/gin-gonic/gin"
)
func AuthMiddleware ( ) func ( c * gin. Context) {
return func ( c * gin. Context) {
token := c. Request. Header. Get ( "token" )
var u model. User
if rows := mysql. DB. Where ( "token = ?" , token) . First ( & u) . RowsAffected; rows != 1 {
c. JSON ( 403 , gin. H{ "msg" : "token 错误" } )
c. Abort ( )
return
}
c. Set ( "UserId" , u. Id)
c. Next ( )
}
}
model
book.go
book的模型
package model
type Book struct {
Id int64 `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"not null" binding:"required"`
Desc string `json:"desc"`
User [ ] User `gorm:"many2many:book_users"`
}
func ( Book) TableName ( ) string {
return "book"
}
user.go
user的模型
package model
type User struct {
Id int64 `json:"id" gorm:"primaryKey"`
Username string `json:"username" gorm:"not null" binding:"required"`
Password string `json:"password" gorm:"not null" binding:"required"`
Token string `json:"token"`
}
func ( User) TableName ( ) string {
return "user"
}
user_m2m_book.go
user和book的中间表模型
package model
type BookUser struct {
UserID int64 `gorm:"primaryKey"`
BookID int64 `gorm:"primaryKey"`
}
router
api_router.go
路由相关
package router
import (
"bookManage/contraller"
"bookManage/middleware"
"github.com/gin-gonic/gin"
)
func LoadApiRouter ( r * gin. Engine) {
r. POST ( "/register" , contraller. RegisterHandler)
r. POST ( "/login" , contraller. LoginHandler)
v1 := r. Group ( "/api/v1" )
v1. Use ( middleware. AuthMiddleware ( ) )
v1. POST ( "book" , contraller. CreateBookHandler)
v1. GET ( "book" , contraller. GetBookListHandler)
v1. GET ( "book/:id" , contraller. GetBookDetailHandler)
v1. PUT ( "book" , contraller. UpdateBookHandler)
v1. DELETE ( "book/:id" , contraller. DeleteBookHandler)
}
init_router
初始化路由
package router
import "github.com/gin-gonic/gin"
func InitRouter ( ) * gin. Engine {
r := gin. Default ( )
LoadApiRouter ( r)
return r
}
main.go
主函数,入口
package main
import (
"bookManage/dao/mysql"
"bookManage/router"
)
func main ( ) {
mysql. InitMysql ( )
r := router. InitRouter ( )
r. Run ( ":8000" )
}