Go实战 | 使用Go-Fiber采用分层架构搭建一个简单的Web服务

前言

📢博客主页:程序源⠀-CSDN博客

📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!

一、环境准备、示例介绍

Go语言安装,GoLand编辑器
这个示例实现了一个简单的待办事项(todo)管理系统。
目录详情

新建一个fiber-todos文件夹,在目录中新建如下文件

二、代码编写

采用分层架构搭建一个简单的Web服务有助于提高代码的可维护性和可扩展性。我们将把应用程序分为以下几个层次:

  1. Handler(处理器层):处理HTTP请求。

  2. Service(服务层):包含业务逻辑。

  3. Repository(仓库层):处理数据访问逻辑。

  4. Model(模型层):定义数据结构。

2.1 Handler(处理器层)

Go 复制代码
package handler

import (
	"fiber-todos/model"
	"fiber-todos/service"
	"github.com/gofiber/fiber/v2"
)

type TodoHandler struct {
	service service.TodoService
}

func NewTodoHandler(service service.TodoService) *TodoHandler {
	return &TodoHandler{service: service}
}

func (h *TodoHandler) GetTodos(c *fiber.Ctx) error {
	todos := h.service.GetAllTodos()
	return c.JSON(todos)
}

func (h *TodoHandler) GetTodoByID(c *fiber.Ctx) error {
	id := c.Params("id")
	todo, found := h.service.GetTodoByID(id)
	if !found {
		return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Todo not found"})
	}
	return c.JSON(todo)
}

func (h *TodoHandler) CreateTodo(c *fiber.Ctx) error {
	todo := new(model.Todo)
	if err := c.BodyParser(todo); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse JSON"})
	}
	createdTodo := h.service.CreateTodo(*todo)
	return c.Status(fiber.StatusCreated).JSON(createdTodo)
}

func (h *TodoHandler) UpdateTodo(c *fiber.Ctx) error {
	id := c.Params("id")
	todo := new(model.Todo)
	if err := c.BodyParser(todo); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse JSON"})
	}
	updatedTodo, found := h.service.UpdateTodo(id, *todo)
	if !found {
		return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Todo not found"})
	}
	return c.JSON(updatedTodo)
}

func (h *TodoHandler) DeleteTodo(c *fiber.Ctx) error {
	id := c.Params("id")
	deleted := h.service.DeleteTodo(id)
	if !deleted {
		return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Todo not found"})
	}
	return c.SendStatus(fiber.StatusNoContent)
}

2.2 Service(服务层)

Go 复制代码
package service

import (
	"fiber-todos/model"
	"fiber-todos/repository"
)

type TodoService interface {
	GetAllTodos() []model.Todo
	GetTodoByID(id string) (model.Todo, bool)
	CreateTodo(todo model.Todo) model.Todo
	UpdateTodo(id string, todo model.Todo) (model.Todo, bool)
	DeleteTodo(id string) bool
}

type todoService struct {
	repo repository.TodoRepository
}

func NewTodoService(repo repository.TodoRepository) TodoService {
	return &todoService{repo: repo}
}

func (s *todoService) GetAllTodos() []model.Todo {
	return s.repo.GetAll()
}

func (s *todoService) GetTodoByID(id string) (model.Todo, bool) {
	return s.repo.GetByID(id)
}

func (s *todoService) CreateTodo(todo model.Todo) model.Todo {
	return s.repo.Create(todo)
}

func (s *todoService) UpdateTodo(id string, todo model.Todo) (model.Todo, bool) {
	return s.repo.Update(id, todo)
}

func (s *todoService) DeleteTodo(id string) bool {
	return s.repo.Delete(id)
}

2.3 Repository(仓库层)

Go 复制代码
package repository

import (
	"fiber-todos/model"
	"github.com/google/uuid"
)

type TodoRepository interface {
	GetAll() []model.Todo
	GetByID(id string) (model.Todo, bool)
	Create(todo model.Todo) model.Todo
	Update(id string, todo model.Todo) (model.Todo, bool)
	Delete(id string) bool
}

type InMemoryTodoRepository struct {
	todos []model.Todo
}

func NewInMemoryTodoRepository() TodoRepository {
	return &InMemoryTodoRepository{
		todos: []model.Todo{},
	}
}

func (r *InMemoryTodoRepository) GetAll() []model.Todo {
	return r.todos
}

func (r *InMemoryTodoRepository) GetByID(id string) (model.Todo, bool) {
	for _, todo := range r.todos {
		if todo.ID == id {
			return todo, true
		}
	}
	return model.Todo{}, false
}

func (r *InMemoryTodoRepository) Create(todo model.Todo) model.Todo {
	todo.ID = uuid.New().String()
	r.todos = append(r.todos, todo)
	return todo
}

func (r *InMemoryTodoRepository) Update(id string, updatedTodo model.Todo) (model.Todo, bool) {
	for i, todo := range r.todos {
		if todo.ID == id {
			r.todos[i].Title = updatedTodo.Title
			r.todos[i].Done = updatedTodo.Done
			return r.todos[i], true
		}
	}
	return model.Todo{}, false
}

func (r *InMemoryTodoRepository) Delete(id string) bool {
	for i, todo := range r.todos {
		if todo.ID == id {
			r.todos = append(r.todos[:i], r.todos[i+1:]...)
			return true
		}
	}
	return false
}

2.4 Model(模型层)

Go 复制代码
package model

type Todo struct {
	ID    string `json:"id"`
	Title string `json:"title"`
	Done  bool   `json:"done"`
}

三、运行结果

在终端中打开项目,运行项目

go run main.go

再打开一个新的终端

这里使用 Invoke-WebRequest 发送 POST 请求

Go 复制代码
$headers = @{
    "Content-Type" = "application/json"
}

$body = @{
    "title" = "Learn Fiber"
    "done" = $false
} | ConvertTo-Json

Invoke-WebRequest -Uri "http://localhost:3000/todos" -Method POST -Headers $headers -Body $body

解析:

Headers 字典创建:

Go 复制代码
$headers = @{
    "Content-Type" = "application/json"
}

Body 对象创建:

Go 复制代码
$body = @{
    "title" = "Learn Fiber"
    "done" = $false
} | ConvertTo-Json

发送 POST 请求:

Go 复制代码
curl -X POST http://localhost:3000/todos -H "Content-Type: application/json" -d '{"title": "Learn Fiber", "done": false}'

响应结果:

成功发送了 POST 请求

相关推荐
Algorithm15762 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
shinelord明11 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
Monly2118 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
boligongzhu19 分钟前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
Eric.Lee202119 分钟前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
goTsHgo21 分钟前
在 Spring Boot 的 MVC 框架中 路径匹配的实现 详解
spring boot·后端·mvc
7yewh21 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
waicsdn_haha33 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
_WndProc35 分钟前
C++ 日志输出
开发语言·c++·算法
Q_192849990643 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端