golang项目CRUD示例

目录

项目结构

数据库的连接

实体类

Repository层(crud)

Service层

接口层

main.go

Router.go


项目结构

复制代码
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
}
相关推荐
打工仔折腾 AI3 分钟前
从Attention到BERT:双向预训练语言模型到底解决了什么问题
人工智能·后端·python·深度学习·语言模型·bert
谢亮_vipxieliang5 分钟前
Stream API 不是银弹:常见坑与性能建议
java·开发语言
迅猛龙办公室18 分钟前
实现第一个python程序(HelloWorld)
开发语言·python
phltxy21 分钟前
C 语言动态内存管理:从申请空间到安全释放
c语言·开发语言·ui
可乐鸡翅yeah_25 分钟前
M3U8 防盗链 URL‑Token 签名,新手开发实操避坑
开发语言·javascript·ios·音视频·safari
2603_9658966236 分钟前
JS原型与原型链|对象继承与实例底层原理
开发语言·javascript·原型模式
拉格朗日(Lagrange)39 分钟前
【第2 章】WorkBuddy 从入门到高手
开发语言·python
yujunl41 分钟前
在U9C订单列表上开放多个按钮层叠的问题解决
开发语言
喆星时瑜1 小时前
Win10/11 安装 R 与 RStudio 详细图文教程
开发语言·r语言·安装
lizhongxuan1 小时前
Agent Sandbox: Firecracker 任务生命周期
后端