使用 Gorilla Mux 和 CockroachDB 编写可维护 RESTful API(下)

简介: 本文将使用功能强大的 Gorilla Mux、GORM 和 CockroachDB 编写可维护 RESTful API。

3.3 handler.go

回到 mybook 文件夹下,创建 handler.go

package main
import (
  "encoding/json"
  "net/http"
  "mybook/model"
  "github.com/gorilla/mux"
  "gorm.io/gorm"
)
type Server struct {
  db *gorm.DB
}
type UpdateBook struct {
  Price       float64 `json:"price"`
  Description string  `json:"decription"`
  Category    string  `json:"category"`
}
func NewServer(db *gorm.DB) *Server {
  return &Server{db: db}
}
func (s *Server) RegisterRouter(router *mux.Router) {
  router.HandleFunc("/books", s.getBooks)
  router.HandleFunc("/book/{id}", s.getBook).Methods("GET")
  router.HandleFunc("/book", s.createBook).Methods("POST")
  router.HandleFunc("/book/{id}", s.updateBook).Methods("PUT")
  router.HandleFunc("/book/{id}", s.deleteBook).Methods("DELETE")
}
func (s *Server) getBooks(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json;charset=UTF-8")
  var books []model.Book
  if err := s.db.Find(&books).Error; err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  w.WriteHeader(http.StatusOK)
  json.NewEncoder(w).Encode(books)
}
func (s *Server) createBook(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  var book model.Book
  if err := json.NewDecoder(r.Body).Decode(&book); err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  newBook := model.Book{Price: book.Price, Description: book.Description, Category: book.Category}
  if err := s.db.Create(newBook).Error; err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  w.WriteHeader(http.StatusOK)
  json.NewEncoder(w).Encode(newBook)
}
func (s *Server) getBook(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  var book model.Book
  vars := mux.Vars(r)
  id := vars["id"]
  if err := s.db.Where("id = ?", id).First(&book).Error; err != nil {
    http.Error(w, err.Error(), http.StatusNotFound)
    return
  }
  w.WriteHeader(http.StatusOK)
  json.NewEncoder(w).Encode(book)
}
func (s *Server) updateBook(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  var updateBook UpdateBook
  var book model.Book
  vars := mux.Vars(r)
  id := vars["id"]
  if err := json.NewDecoder(r.Body).Decode(&updateBook); err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  if err := s.db.Where("id = ?", id).First(&book).Error; err != nil {
    http.Error(w, err.Error(), http.StatusNotFound)
    return
  }
  if err := s.db.Model(&book).Updates(&model.Book{
    Price:       updateBook.Price,
    Description: updateBook.Description,
    Category:    updateBook.Category}).Error; err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  w.WriteHeader(http.StatusOK)
  json.NewEncoder(w).Encode(book)
}
func (s *Server) deleteBook(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  var book model.Book
  vars := mux.Vars(r)
  id := vars["id"]
  if err := s.db.Where("id = ?", id).First(&book).Error; err != nil {
    http.Error(w, err.Error(), http.StatusNotFound)
    return
  }
  if err := s.db.Delete(&book).Error; err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  w.WriteHeader(http.StatusOK)
  json.NewEncoder(w).Encode("Book Deleted Successfully!")
}

3.4 main.go

main.go 中,我们初始化数据库,创建一个路由器实例,将变量 db 作为参数传递给我们的服务器初始化,然后将路由器实例作为参数传递给方法 registryRouter()。然后,我们使用侦听器来运行服务器。

package main
import (
  "log"
  "net/http"
  "github.com/gorilla/mux"
  "mybook/model"
)
func main() {
  db, err := model.SetupDB()
  if err != nil {
    log.Println("Failed setting up database")
  }
  router := mux.NewRouter()
  server := NewServer(db)
  server.RegisterRouter(router)
  log.Fatal(http.ListenAndServe(":8000", router))
}


当写完所有的程序后,运行 go run . 命令,启动成功如下:


网络异常,图片无法展示
|


此时,运行 cockcoach sql 进入数据库命令行,然后运行 show tables; 命令,可以看到在默认数据库 defaultdb 中已经生成一个 books 数据库表,如下所示:


网络异常,图片无法展示
|


我们执行 select * from books 查看我们生成的表信息:


网络异常,图片无法展示
|


可以看到已经生成了我们定义的字段 id、name、author、description、price、category 以外,GORM 还默认帮忙增加了 created_at (创建时间)、updated_at(更新时间)和 deleted_at(删除时间)三个字段。

4 API 测试

为了方便我们测试这个 book 应用的 API 功能正常,我们将利用 APIfox 工具来进行测试。先在数据库中新增一条记录,如下:


INSERT INTO books (id, name, author, description, price, category)VALUES(1, 'Go程序设计语言(英文版)', '艾伦A.A.多诺万 (Alan A.A.Donovan) / 布莱恩W.柯尼汉 (Brian W.Kemighan)', '被誉为 Go 语言圣经的书,非常值得一读', 79.00, 'Golang');

复制代码


网络异常,图片无法展示
|


获取书籍清单/books测试


插入成功,我们访问后台 http://127.0.0.1:8000/books 路径,可以看到如下成功,说明获取书籍清单的 API 是成功的,恭喜。


网络异常,图片无法展示
|


接下来为了测试,下载 Linux 版本的 Apifox 帮助我们快速测试其他接口。


获取一本书籍/book/1 测试


网络异常,图片无法展示
|

总结

本文利用 Go 语言中非常实用的 Gorilla Mux 和 GORM 库、结合分布式 CockroachDB 数据库编写了一个简易的图书的 Restful API,最后通过 Apifox 测试工具验证了服务器 API 的正确。


显然本文还是有很多不足,比如并没有充分利用到 CockroachDB 数据库的分布式特性,而且没有为 API 编写测试代码,测试并不一定完善,这些都可以给到读者一些优化思路。


相关文章
|
5天前
|
JSON 缓存 JavaScript
深入浅出:使用Node.js构建RESTful API
在这个数字时代,API已成为软件开发的基石之一。本文旨在引导初学者通过Node.js和Express框架快速搭建一个功能完备的RESTful API。我们将从零开始,逐步深入,不仅涉及代码编写,还包括设计原则、最佳实践及调试技巧。无论你是初探后端开发,还是希望扩展你的技术栈,这篇文章都将是你的理想指南。
|
2天前
|
JSON 缓存 测试技术
构建高效RESTful API的后端实践指南####
本文将深入探讨如何设计并实现一个高效、可扩展且易于维护的RESTful API。不同于传统的摘要概述,本节将直接以行动指南的形式,列出构建RESTful API时必须遵循的核心原则与最佳实践,旨在为开发者提供一套直接可行的实施框架,快速提升API设计与开发能力。 ####
|
8天前
|
存储 API 数据库
使用Python和Flask构建简单的RESTful API
使用Python和Flask构建简单的RESTful API
|
8天前
|
JSON 关系型数据库 测试技术
使用Python和Flask构建RESTful API服务
使用Python和Flask构建RESTful API服务
|
13天前
|
JSON JavaScript API
深入浅出Node.js:从零开始构建RESTful API
【10月更文挑战第39天】 在数字化时代的浪潮中,API(应用程序编程接口)已成为连接不同软件应用的桥梁。本文将带领读者从零基础出发,逐步深入Node.js的世界,最终实现一个功能完备的RESTful API。通过实践,我们将探索如何利用Node.js的异步特性和强大的生态系统来构建高效、可扩展的服务。准备好迎接代码和概念的碰撞,一起解锁后端开发的新篇章。
|
3天前
|
JSON API 开发者
深入理解RESTful API设计原则
在数字化时代,API已成为连接不同软件应用的桥梁。本文旨在探讨RESTful API设计的基本原则和最佳实践,帮助开发者构建高效、可扩展的网络服务接口。通过解析REST架构风格的核心概念,我们将了解如何设计易于理解和使用的API,同时保证其性能和安全性。
|
3天前
|
安全 测试技术 API
构建高效RESTful API:后端开发的艺术与实践####
在现代软件开发的浩瀚星空中,RESTful API如同一座桥梁,连接着前端世界的绚丽多彩与后端逻辑的深邃复杂。本文旨在探讨如何精心打造一款既高效又易于维护的RESTful API,通过深入浅出的方式,剖析其设计原则、实现技巧及最佳实践,为后端开发者提供一份实用的指南。我们不深入晦涩的理论,只聚焦于那些能够即刻提升API品质与开发效率的关键点,让你的API在众多服务中脱颖而出。 ####
11 0
|
17天前
|
SQL 缓存 测试技术
构建高性能RESTful API:最佳实践与避坑指南###
—— 本文深入探讨了构建高性能RESTful API的关键技术要点,从设计原则、状态码使用、版本控制到安全性考虑,旨在为开发者提供一套全面的最佳实践框架。通过避免常见的设计陷阱,本文将指导你如何优化API性能,提升用户体验,确保系统的稳定性和可扩展性。 ###
54 12
|
3月前
|
JSON 前端开发 API
打造高效后端:RESTful API 设计的最佳实践
【9月更文挑战第14天】在数字化时代,后端开发是构建强大、灵活和可维护应用程序的基石。本文将深入探讨如何设计高效的RESTful API,包括清晰的资源定义、合理的HTTP方法使用、URL结构规划、状态码的准确返回以及数据格式的设计。通过这些实践,开发者能够创建出既符合行业标准又易于维护和扩展的API,为前端提供强大的数据支持,确保整个应用的稳定性和性能。
170 74
|
18天前
|
JSON 缓存 API
构建高效RESTful API的最佳实践
【10月更文挑战第34天】在数字时代的浪潮中,后端开发扮演着至关重要的角色。本文将带你深入探索如何构建高效的RESTful API,从设计原则到实际编码技巧,再到性能优化和错误处理,我们将一一解锁这些技能。你将学会如何打造一个既优雅又强大的后端服务,让你的应用程序在激烈的市场竞争中脱颖而出。那么,让我们一起踏上这段精彩的旅程吧!
28 2
下一篇
无影云桌面