首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >使用Golang和MySQL开发预约系统

使用Golang和MySQL开发预约系统

原创
作者头像
flyskyocean
发布2025-01-21 11:57:13
发布2025-01-21 11:57:13
3330
举报

在当今数字化的时代,预约系统在各个领域都得到了广泛的应用,如医院挂号预约、餐厅预订、旅行酒店预订等。本文将详细介绍如何使用Golang和MySQL开发一个简单的预约系统,涵盖系统的需求分析、数据库设计、代码实现以及测试和部署等方面。

需求分析

在开发预约系统之前,首先需要明确系统的功能和需求。一个基本的预约系统通常需要具备以下功能:

用户注册与登录:用户需要能够注册账号并登录系统,以便进行预约操作。登录后,用户可以查看自己的预约记录,并根据需要进行修改或取消预约。

服务提供者管理:系统需要支持添加、编辑和删除服务提供者(如医生、餐厅服务员等),并为其设置可预约的时间段。

预约功能:用户可以选择服务提供者和预约时间段,提交预约请求。系统需要进行冲突检查,确保同一时间段内不会被重复预约。

预约确认与提醒:预约成功后,系统应向用户发送确认通知,并根据用户设置提供预约提醒功能。

数据库设计

根据需求分析,我们设计以下数据库表结构:

(一)用户表(users)

存储用户信息,包括用户ID、用户名、密码、邮箱等。

代码语言:javascript
复制
CREATE TABLE users (
    user_id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(100)
);

(二)服务提供者表(providers)

存储服务提供者的信息,包括提供者ID、名称、描述等。

代码语言:javascript
复制
CREATE TABLE providers (
    provider_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    description TEXT
);

(三)预约表(appointments)

存储预约信息,包括预约ID、用户ID、提供者ID、预约时间段、状态等。

代码语言:javascript
复制
CREATE TABLE appointments (
    appointment_id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    provider_id INT,
    appointment_time DATETIME,
    status VARCHAR(20),
    FOREIGN KEY (user_id) REFERENCES users(user_id),
    FOREIGN KEY (provider_id) REFERENCES providers(provider_id)
);

Golang代码实现

(一)项目结构

一个典型的Golang项目的结构如下:

代码语言:javascript
复制
appointment-system/
├── config/
│   └── db-config.json
├── controllers/
│   ├── appointment_controller.go
│   ├── user_controller.go
│   └── provider_controller.go
├── models/
│   ├── appointment.go
│   ├── user.go
│   └── provider.go
├── routes/
│   └── routes.go
├── main.go
└── utils/
    └── utils.go

(二)配置文件(config/db-config.json)

用于存储数据库连接配置。

代码语言:javascript
复制
{
    "host": "localhost",
    "port": 3306,
    "user": "root",
    "password": "",
    "dbname": "appointment_system"
}

(三)数据库连接(utils/utils.go)

创建一个函数用于读取配置文件并建立数据库连接。

代码语言:javascript
复制
package utils

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "io/ioutil"
    _ "github.com/go-sql-driver/mysql"
)

type DBConfig struct {
    Host     string `json:"host"`
    Port     int    `json:"port"`
    User     string `json:"user"`
    Password string `json:"password"`
    DBName   string `json:"dbname"`
}

func GetDBConnection() (*sql.DB, error) {
    // 读取配置文件
    configFile, err := ioutil.ReadFile("config/db-config.json")
    if err != nil {
        return nil, err
    }

    var config DBConfig
    json.Unmarshal(configFile, &config)

    // 构建数据库连接字符串
    dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4",
        config.User, config.Password, config.Host, config.Port, config.DBName)

    // 连接数据库
    db, err := sql.Open("mysql", dsn)
    if err!= nil {
        return nil, err
    }

    return db, nil
}

(四)模型定义(models/)

用户模型(models/user.go)
代码语言:javascript
复制
package models

type User struct {
    UserID   int    `json:"user_id"`
    Username string `json:"username"`
    Password string `json:"password"`
    Email    string `json:"email"`
}
服务提供者模型(models/provider.go)
代码语言:javascript
复制
package models

type Provider struct {
    ProviderID   int    `json:"provider_id"`
    Name         string `json:"name"`
    Description  string `json:"description"`
}
预约模型(models/appointment.go)
代码语言:javascript
复制
package models

import (
    "time"
)

type Appointment struct {
    AppointmentID   int       `json:"appointment_id"`
    UserID          int       `json:"user_id"`
    ProviderID      int       `json:"provider_id"`
    AppointmentTime time.Time `json:"appointment_time"`
    Status          string    `json:"status"`
}

(五)控制器实现(controllers/)

用户控制器(controllers/user_controller.go)
代码语言:javascript
复制
package controllers

import (
    "database/sql"
    "encoding/json"
    "net/http"
    "appointment-system/models"
    "appointment-system/utils"
)

func RegisterHandler(w http.ResponseWriter, r *http.Request) {
    // 解析请求体
    var user models.User
    json.NewDecoder(r.Body).Decode(&user)

    // 保存用户信息到数据库
    db, err := utils.GetDBConnection()
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer db.Close()

    res, err := db.Exec("INSERT INTO users (username, password, email) VALUES (?, ?, ?)",
        user.Username, user.Password, user.Email)
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    userID, _ := res.LastInsertId()
    user.UserID = int(userID)
    json.NewEncoder(w).Encode(user)
}

func LoginHandler(w http.ResponseWriter, r *http.Request) {
    // 解析请求体
    var loginUser models.User
    json.NewDecoder(r.Body).Decode(&loginUser)

    // 验证用户登录信息
    db, err := utils.GetDBConnection()
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer db.Close()

    var user models.User
    err = db.QueryRow("SELECT user_id, username, password, email FROM users WHERE username =? AND password =?",
        loginUser.Username, loginUser.Password).Scan(&user.UserID, &user.Username, &user.Password, &user.Email)
    if err!= nil {
        http.Error(w, "Invalid username or password", http.StatusUnauthorized)
        return
    }

    json.NewEncoder(w).Encode(user)
}
服务提供者控制器(controllers/provider_controller.go)
代码语言:javascript
复制
package controllers

import (
    "database/sql"
    "encoding/json"
    "net/http"
    "appointment-system/models"
    "appointment-system/utils"
)

func CreateProviderHandler(w http.ResponseWriter, r *http.Request) {
    // 解析请求体
    var provider models.Provider
    json.NewDecoder(r.Body).Decode(&provider)

    // 保存服务提供者信息到数据库
    db, err := utils.GetDBConnection()
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer db.Close()

    res, err := db.Exec("INSERT INTO providers (name, description) VALUES (?, ?)",
        provider.Name, provider.Description)
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    providerID, _ := res.LastInsertId()
    provider.ProviderID = int(providerID)
    json.NewEncoder(w).Encode(provider)
}
预约控制器(controllers/appointment_controller.go)
代码语言:javascript
复制
package controllers

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "net/http"
    "time"
    "appointment-system/models"
    "appointment-system/utils"
)

func CreateAppointmentHandler(w http.ResponseWriter, r *http.Request) {
    // 解析请求体
    var appointmentRequest struct {
        UserID          int       `json:"user_id"`
        ProviderID      int       `json:"provider_id"`
        AppointmentTime time.Time `json:"appointment_time"`
    }
    json.NewDecoder(r.Body).Decode(&appointmentRequest)

    // 检查预约时间是否冲突
    db, err := utils.GetDBConnection()
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer db.Close()

    var count int
    err = db.QueryRow("SELECT COUNT(*) FROM appointments WHERE provider_id =? AND appointment_time =?",
        appointmentRequest.ProviderID, appointmentRequest.AppointmentTime).Scan(&count)
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    if count > 0 {
        http.Error(w, "The appointment time is already taken", http.StatusBadRequest)
        return
    }

    // 创建预约记录
    var appointment models.Appointment
    appointment.UserID = appointmentRequest.UserID
    appointment.ProviderID = appointmentRequest.ProviderID
    appointment.AppointmentTime = appointmentRequest.AppointmentTime
    appointment.Status = "pending"

    res, err := db.Exec("INSERT INTO appointments (user_id, provider_id, appointment_time, status) VALUES (?, ?, ?, ?)",
        appointment.UserID, appointment.ProviderID, appointment.AppjectoryTime, appointment.Status)
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    appointmentID, _ := res.LastInsertId()
    appointment.AppointmentID = int(appointmentID)
    json.NewEncoder(w).Encode(appointment)
}

(六)路由设置(routes/routes.go)

定义系统的路由,将不同的URL路径与相应的控制器函数关联起来。

代码语言:javascript
复制
package routes

import (
    "net/http"
    "github.com/gorilla/mux"
    "appointment-system/controllers"
)

func InitRoutes() *mux.Router {
    router := mux.NewRouter()

    router.HandleFunc("/register", controllers.RegisterHandler).Methods("POST")
    router.HandleFunc("/login", controllers.LoginHandler).Methods("POST")
    router.HandleFunc("/providers", controllers.CreateProviderHandler).Methods("POST")
    router.HandleFunc("/appointments", controllers.CreateAppointmentHandler).Methods("POST")

    return router
}

(七)主函数(main.go)

程序的入口文件,配置数据库连接并启动HTTP服务器。

代码语言:javascript
复制
package main

import (
    "log"
    "net/http"
    "appointment-system/routes"
)

func main() {
    router := routes.InitRoutes()

    log.Fatal(http.ListenAndServe(":8080", router))
}

测试与部署

在项目开发完成后,需要进行全面的测试以确保系统的稳定性和功能性。测试包括单元测试、集成测试和功能测试等。

单元测试可以使用Go自带的测试框架testing包来编写,对各个模块的功能进行单独测试。集成测试则测试不同模块之间的交互是否正常。功能测试则模拟实际用户场景,验证系统是否满足需求。

测试通过后,可以将系统部署到生产环境中。可以使用Docker容器化部署,将系统打包成一个独立的容器,方便部署和管理。也可以使用云服务提供商(如阿里云、腾讯云等)的云服务器进行部署,根据实际需求选择合适的部署方式。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求分析
  • 数据库设计
    • (一)用户表(users)
    • (二)服务提供者表(providers)
    • (三)预约表(appointments)
  • Golang代码实现
    • (一)项目结构
    • (二)配置文件(config/db-config.json)
    • (三)数据库连接(utils/utils.go)
    • (四)模型定义(models/)
      • 用户模型(models/user.go)
      • 服务提供者模型(models/provider.go)
      • 预约模型(models/appointment.go)
    • (五)控制器实现(controllers/)
      • 用户控制器(controllers/user_controller.go)
      • 服务提供者控制器(controllers/provider_controller.go)
      • 预约控制器(controllers/appointment_controller.go)
    • (六)路由设置(routes/routes.go)
    • (七)主函数(main.go)
  • 测试与部署
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档