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

2024-06-07 05:12

本文主要是介绍Go实战 | 使用Go-Fiber采用分层架构搭建一个简单的Web服务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

📢博客主页:程序源⠀-CSDN博客
📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!

一、环境准备、示例介绍

Go语言安装,GoLand编辑器

 这个示例实现了一个简单的待办事项(todo)管理系统。

目录详情

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

二、代码编写

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

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

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

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

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

2.1  Handler(处理器层)

package handlerimport ("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(服务层)

package serviceimport ("fiber-todos/model""fiber-todos/repository"
)type TodoService interface {GetAllTodos() []model.TodoGetTodoByID(id string) (model.Todo, bool)CreateTodo(todo model.Todo) model.TodoUpdateTodo(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(仓库层)

package repositoryimport ("fiber-todos/model""github.com/google/uuid"
)type TodoRepository interface {GetAll() []model.TodoGetByID(id string) (model.Todo, bool)Create(todo model.Todo) model.TodoUpdate(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.Titler.todos[i].Done = updatedTodo.Donereturn 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(模型层)

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

三、运行结果

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

go run main.go

再打开一个新的终端

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

$headers = @{"Content-Type" = "application/json"
}$body = @{"title" = "Learn Fiber""done" = $false
} | ConvertTo-JsonInvoke-WebRequest -Uri "http://localhost:3000/todos" -Method POST -Headers $headers -Body $body

解析:

Headers 字典创建:

$headers = @{"Content-Type" = "application/json"
}

Body 对象创建:

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

发送 POST 请求:

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

响应结果:

 成功发送了 POST 请求

这篇关于Go实战 | 使用Go-Fiber采用分层架构搭建一个简单的Web服务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1038256

相关文章

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3