使用Golang开发任务管理系统需要结合其高效的并发特性和简洁的语法,从需求梳理到功能落地逐步推进,最终实现稳定可用的任务管理工具。

需求分析与数据库设计
任务管理系统的核心需求通常包括任务的增删改查、状态更新、用户关联等,首先需要设计对应的数据库表结构。这里使用MySQL作为存储引擎,核心任务表结构如下:
-- 创建任务表
CREATE TABLE IF NOT EXISTS task (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '任务ID',
title VARCHAR(100) NOT NULL COMMENT '任务标题',
content TEXT COMMENT '任务内容',
status TINYINT NOT NULL DEFAULT 0 COMMENT '任务状态 0待处理 1进行中 2已完成',
user_id BIGINT NOT NULL COMMENT '关联用户ID',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务信息表';
项目基础结构搭建
首先初始化Golang项目,安装必要的依赖包,这里使用gin作为web框架,gorm作为ORM工具操作数据库:
# 初始化项目 go mod init task_manager # 安装依赖 go get -u github.com/gin-gonic/gin go get -u gorm.io/gorm go get -u gorm.io/driver/mysql
项目目录结构可以按照功能模块划分:
- config:存放数据库、服务配置
- model:定义数据模型
- handler:处理HTTP请求逻辑
- service:实现核心业务逻辑
- router:定义路由规则
核心功能实现
数据库连接初始化
在config目录下编写数据库初始化代码:
package config
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
func InitDB() error {
dsn := "root:password@tcp(127.0.0.1:3306)/task_db?charset=utf8mb4&parseTime=True&loc=Local"
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
return fmt.Errorf("数据库连接失败: %v", err)
}
// 自动迁移表结构
err = DB.AutoMigrate(&model.Task{})
if err != nil {
return fmt.Errorf("表迁移失败: %v", err)
}
return nil
}
数据模型定义
在model目录下定义任务模型,对应数据库表结构:
package model
import "time"
type Task struct {
ID int64 `gorm:"primaryKey;autoIncrement" json:"id"`
Title string `gorm:"type:varchar(100);not null" json:"title"`
Content string `gorm:"type:text" json:"content"`
Status int `gorm:"type:tinyint;not null;default:0" json:"status"`
UserID int64 `gorm:"type:bigint;not null" json:"user_id"`
CreateTime time.Time `gorm:"autoCreateTime" json:"create_time"`
UpdateTime time.Time `gorm:"autoUpdateTime" json:"update_time"`
}
任务增删改查接口实现
在service层实现任务的核心业务逻辑:
package service
import (
"task_manager/config"
"task_manager/model"
)
// 创建任务
func CreateTask(title, content string, userId int64) (*model.Task, error) {
task := &model.Task{
Title: title,
Content: content,
Status: 0,
UserID: userId,
}
result := config.DB.Create(task)
if result.Error != nil {
return nil, result.Error
}
return task, nil
}
// 查询用户所有任务
func GetTasksByUserId(userId int64) ([]model.Task, error) {
var tasks []model.Task
result := config.DB.Where("user_id = ?", userId).Find(&tasks)
if result.Error != nil {
return nil, result.Error
}
return tasks, nil
}
// 更新任务状态
func UpdateTaskStatus(taskId, userId int64, status int) error {
result := config.DB.Model(&model.Task{}).
Where("id = ? AND user_id = ?", taskId, userId).
Update("status", status)
if result.Error != nil {
return result.Error
}
if result.RowsAffected == 0 {
return fmt.Errorf("任务不存在或无权限修改")
}
return nil
}
// 删除任务
func DeleteTask(taskId, userId int64) error {
result := config.DB.Where("id = ? AND user_id = ?", taskId, userId).Delete(&model.Task{})
if result.Error != nil {
return result.Error
}
if result.RowsAffected == 0 {
return fmt.Errorf("任务不存在或无权限删除")
}
return nil
}
在handler层编写HTTP接口处理逻辑:
package handler
import (
"net/http"
"strconv"
"task_manager/service"
"github.com/gin-gonic/gin"
)
// 创建任务接口
func CreateTaskHandler(c *gin.Context) {
var req struct {
Title string `json:"title" binding:"required"`
Content string `json:"content"`
UserID int64 `json:"user_id" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
task, err := service.CreateTask(req.Title, req.Content, req.UserID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": task})
}
// 查询任务接口
func GetTasksHandler(c *gin.Context) {
userIdStr := c.Query("user_id")
userId, err := strconv.ParseInt(userIdStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的用户ID"})
return
}
tasks, err := service.GetTasksByUserId(userId)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": tasks})
}
// 更新任务状态接口
func UpdateTaskStatusHandler(c *gin.Context) {
taskIdStr := c.Param("id")
taskId, err := strconv.ParseInt(taskIdStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的任务ID"})
return
}
var req struct {
UserID int64 `json:"user_id" binding:"required"`
Status int `json:"status" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err = service.UpdateTaskStatus(taskId, req.UserID, req.Status)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "更新成功"})
}
// 删除任务接口
func DeleteTaskHandler(c *gin.Context) {
taskIdStr := c.Param("id")
taskId, err := strconv.ParseInt(taskIdStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的任务ID"})
return
}
userIdStr := c.Query("user_id")
userId, err := strconv.ParseInt(userIdStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的用户ID"})
return
}
err = service.DeleteTask(taskId, userId)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}
路由配置
在router目录配置接口路由:
package router
import (
"task_manager/handler"
"github.com/gin-gonic/gin"
)
func InitRouter() *gin.Engine {
r := gin.Default()
taskGroup := r.Group("/tasks")
{
taskGroup.POST("", handler.CreateTaskHandler)
taskGroup.GET("", handler.GetTasksHandler)
taskGroup.PUT("/:id/status", handler.UpdateTaskStatusHandler)
taskGroup.DELETE("/:id", handler.DeleteTaskHandler)
}
return r
}
并发优化与任务调度
Golang的goroutine和channel特性可以用来优化任务调度逻辑,比如实现定时任务提醒、批量任务处理等功能。以下是一个简单的批量任务状态更新示例,利用goroutine并发处理多个任务更新请求:
package service
func BatchUpdateTaskStatus(taskIds []int64, userId int64, status int) error {
errChan := make(chan error, len(taskIds))
for _, taskId := range taskIds {
go func(tid int64) {
err := UpdateTaskStatus(tid, userId, status)
errChan <- err
}(taskId)
}
for i := 0; i < len(taskIds); i++ {
err := <-errChan
if err != nil {
return err
}
}
close(errChan)
return nil
}
启动服务
最后编写main函数启动整个服务:
package main
import (
"task_manager/config"
"task_manager/router"
"log"
)
func main() {
// 初始化数据库
err := config.InitDB()
if err != nil {
log.Fatalf("数据库初始化失败: %v", err)
}
// 初始化路由
r := router.InitRouter()
// 启动服务,监听8080端口
if err := r.Run(":8080"); err != nil {
log.Fatalf("服务启动失败: %v", err)
}
}
完成以上步骤后,就可以启动服务,通过HTTP请求测试任务管理系统的各项功能,后续还可以根据需求扩展用户认证、任务分类、优先级设置等功能。