目录
项目结构
myproject/
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── config/
│ │ └── db.go
│ ├── model/
│ │ └── student.go
│ ├── repository/
│ │ └── student_repo.go
│ ├── service/
│ │ └── student_service.go
│ └── handler/
│ └── student_handler.go
├── pkg/
│ └── utils/
│ └── response.go
├── api/
│ └── swagger.md # 可选
├── scripts/
│ └── run.sh
├── web/ # 可放前端资源
├── go.mod
└── go.sum
数据库的连接
package config
import (
"fmt"
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/schema"
)
var DB *gorm.DB
func InitDB() {
user := "root"
password := "your_password"
host := "127.0.0.1"
port := "3306"
dbname := "students"
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
user, password, host, port, dbname)
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true, // 使用单数表名
},
})
if err != nil {
log.Fatalf("数据库连接失败: %v", err)
}
log.Println("✅ MySQL 数据库连接成功")
}
实体类
go语言中类名和列名首字母大写才能被外部访问,Student对应数据库库students,可以在数据库连接的时候配置使用单数表名
package model
type Student struct {
Id uint `gorm:"primaryKey" json:"id"`
Name string `json:"name"`
Age int `json:"age"`
Major string `json:"major"`
ClassRoom string `json:"class_room"`
}
Repository层(crud)
package repository
import (
"go-student-project/internal/config"
"go-student-project/internal/model"
)
func CreateStudent(student *model.Student) error {
return config.DB.Create(student).Error
}
func GetAllStudents() ([]model.Student, error) {
var students []model.Student
err := config.DB.Find(&students).Error
return students, err
}
func GetStudentByID(id uint) (model.Student, error) {
var student model.Student
err := config.DB.First(&student, id).Error
return student, err
}
func UpdateStudent(student *model.Student) error {
return config.DB.Save(student).Error
}
func DeleteStudent(id uint) error {
return config.DB.Delete(&model.Student{}, id).Error
}
Service层
package service
import (
"go-student-project/internal/model"
"go-student-project/internal/repository"
)
func CreateStudent(student *model.Student) error {
return repository.CreateStudent(student)
}
func GetAllStudents() ([]model.Student, error) {
return repository.GetAllStudents()
}
func GetStudent(id uint) (model.Student, error) {
return repository.GetStudentByID(id)
}
func UpdateStudent(student *model.Student) error {
return repository.UpdateStudent(student)
}
func DeleteStudent(id uint) error {
return repository.DeleteStudent(id)
}
接口层
package handler
import (
"go-student-project/internal/model"
"go-student-project/internal/service"
"go-student-project/pkg/utils"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
func AddStudent(c *gin.Context) {
var student model.Student
if err := c.ShouldBindJSON(&student); err != nil {
utils.Error(c, "参数绑定失败", 400)
return
}
if err := service.CreateStudent(&student); err != nil {
utils.Error(c, "创建失败", 500)
return
}
utils.Success(c, student, "学生创建成功")
}
func ListStudents(c *gin.Context) {
students, err := service.GetAllStudents()
if err != nil {
utils.Error(c, "查询失败", 500)
return
}
utils.Success(c, students, "查询成功")
}
func GetStudent(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
student, err := service.GetStudent(uint(id))
if err != nil {
utils.Error(c, "学生不存在", 404)
return
}
utils.Success(c, student, "查询成功")
}
func UpdateStudent(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var input model.Student
if err := c.ShouldBindJSON(&input); err != nil {
utils.Error(c, "参数错误", 400)
return
}
student, err := service.GetStudent(uint(id))
if err != nil {
utils.Error(c, "学生不存在", 404)
return
}
// 更新允许修改的字段
student.Name = input.Name
student.Age = input.Age
student.Major = input.Major
student.ClassRoom = input.ClassRoom
if err := service.UpdateStudent(&student); err != nil {
utils.Error(c, "更新失败", 500)
return
}
utils.Success(c, student, "更新成功")
}
func DeleteStudent(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
if err := service.DeleteStudent(uint(id)); err != nil {
utils.Error(c, "删除失败", 500)
return
}
utils.Success(c, nil, "删除成功")
}
统一处理(和Java中自定义Result<T>很像)
package utils
import (
"github.com/gin-gonic/gin"
)
func JsonResponse(c *gin.Context, code int, msg string, data any) {
c.JSON(200, gin.H{
"code": code,
"msg": msg,
"data": data,
})
}
func Success(c *gin.Context, data any, msg string) {
JsonResponse(c, 200, msg, data)
}
func Error(c *gin.Context, msg string, code int) {
JsonResponse(c, code, msg, nil)
}
main.go
package main
import (
"go-student-project/internal/config"
"go-student-project/internal/handler"
"github.com/gin-gonic/gin"
)
func main() {
// 初始化数据库
config.InitDB()
config.DB.AutoMigrate(&handler.Student{}) // 或 model.Student
// 初始化路由
r := gin.Default()
studentGroup := r.Group("/student")
{
studentGroup.POST("/", handler.AddStudent)
studentGroup.GET("/", handler.ListStudents)
studentGroup.GET("/:id", handler.GetStudent)
studentGroup.PUT("/:id", handler.UpdateStudent)
studentGroup.DELETE("/:id", handler.DeleteStudent)
}
r.Run(":8080")
}
Router.go
package router
import (
"student/controller"
"github.com/gin-gonic/gin"
)
func InitRouter() *gin.Engine {
engine := gin.Default()
engine.POST("/student", controller.AddStudent)
engine.GET("/student", controller.GetStudent)
engine.PUT("/student/:id", controller.UpdateStudent)
engine.DELETE("/student/:id", controller.DeleteStudent)
return engine
}