用 Golang 编写一个简单的 REST API 让我们开始吧👍🏻

2025-05-25

使用 Golang 编写简单的 REST API

让我们这样做👍🏻

你好😀

在这篇简短的文章中,我将解释如何使用Golang编写REST API并尝试遵循一些最佳实践。

如果需要的话,可以参考这里的源代码。

让我们这样做👍🏻

作为示例,我们将创建一个非常简单的 Post API。

项目结构

让我们跳转到我们的终端并为我们的项目创建一个新目录,然后初始化一个 go 模块。



mkdir postapi
cd postapi
go mod init postapi


Enter fullscreen mode Exit fullscreen mode

注意:模块命名的最佳实践是使用<domain>/<nameOfApp>

现在我们有了这些,让我们用我们最喜欢的代码编辑器打开我们的项目,并创建一个main.go带有 main 包的文件。这将是我们应用程序的入口点。

接下来,创建一个包含文件的包应用程序app.go

捕获 d'écran 2021-04-17 至 19.01.50

在其中,我们将创建一个 App 结构体来表示我们应用的结构。这个结构体包含两个字段:DBRouter
路由器将使用gorilla/mux路由器,因此我们先导入它:

go get -u github.com/gorilla/mux

让我们将它添加到我们的结构中
捕获 d'écran 2021-04-17 至 19.13.02

现在我们将创建一个New()函数,它将负责根据我们的结构返回实际的应用程序。

捕获 d'écran 2021-04-17 至 19.15.15

现在main.go我们可以在我们的文件中调用此函数并创建一个新的应用程序。
捕获 d'écran 2021-04-17 至 19.19.39

好的,应用程序的入口点已经结构化,让我们继续进行路由。

路由

我们使用之前定义的AppRouter来实现基本的路由。 在我们的文件中,我们将创建一个InitRoutes函数,它将在创建应用程序时在New()函数内部被调用。这个函数将成为我们App的接收器。实际上,从现在开始,我们的很多方法都将成为应用程序的接收器。由于结构体App中的 Router 字段属于gorilla/mux router 类型,因此我们可以访问它的方法。
app.go
捕获 d'écran 2021-04-17 至 19.26.38

让我们快速地用一个简单的处理程序来替换索引路由中的nil。为此,handlers.go在我们的 app 包中创建一个文件。我们将在这里存储路由的处理程序。我将创建一个IndexHandler()处理程序,它将返回一个http.HandlerFunc函数,打印“Welcome to Post API”的响应。
捕获 d'écran 2021-04-17 至 20.29.51

现在让我们在路线中调用这个处理程序。
捕获 d'écran 2021-04-17 至 20.32.30

完美,为了测试一下,我们需要回到文件,main.go在我们选择的端口上为应用程序提供服务,并将其重定向到我们的应用程序 Router。此外,我还创建了一个检查函数来打印错误处理的帮助信息。
捕获 d'écran 2021-04-17 至 20.37.45

好的,现在我们可以运行我们的应用程序go run main.go并卷曲端点以查看是否得到响应。

curl http://localhost:9000

捕获 d'écran 2021-04-17 至 21.51.19

太棒了,路由似乎正在起作用!

数据库

现在是时候设置我们的数据库了,我选择使用PostgreSQL,为了避免本地设置,我将在Docker容器上运行我的数据库。

我将使用以下命令:



docker run --name postapidb --env POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres


Enter fullscreen mode Exit fullscreen mode

注意:要停止,您只需运行docker stop postapidb并删除它docker rm postapidb

好的,现在我们已经有一个正在运行的数据库,让我们跳转到代码并在我们的应用程序包内创建一个新的包数据库

让我们创建一个db.go文件,并在其中添加一个接口。我将其命名为PostDB。这个接口就像一个契约(需要实现的方法),如果我们想将数据库用作PostDB数据库,就必须遵守它。首先,PostDB应该实现一个Open()和一个Close( )方法,这两个方法可以返回错误。

我们还将创建一个类似于我们应用程序的DB结构,其中包含一个类型为sqlx DB的字段 db,该字段类似于Go 标准库中database/sql的超集。让我们运行 go get 命令获取sqlxlib/pq(postgres sql 驱动程序),然后实现它。

go get -u github.com/jmoiron/sqlx
go get -u github.com/lib/pq

捕获 d'écran 2021-04-17 至 21.13.57

现在,在编写Open()Close()函数主体之前,我们可以向 App 结构体中添加一个数据库字段,以app.go表明我们在此应用程序中使用PostDB 🙂

捕获 d'écran 2021-04-17 à 21.17.00

接下来,从我们的Open方法开始,让我们打开一个到我们的 postgres 数据库的新连接。

捕获 d'écran 2021-04-17 至 21.24.52

为了建立此连接, sqlx.Open()方法的第二个参数是一个 Postgres 连接字符串。让我们在数据库config.go包中名为 still的单独文件中构建此字符串

捕获 d'écran 2021-04-17 至 21.27.58
捕获 d'écran 2021-04-17 至 21.28.38

我还想创建一个 SQL 模式,用于在连接后运行。如果数据库中没有 posts 表,该模式会创建一个。我们把它添加到一个schemas.go文件中。

捕获 d'écran 2021-04-17 至 23.00.14

捕获 d'écran 2021-04-17 至 21.33.21

我们的Close方法会简单很多。我们只需要从sqlx调用 Close 方法即可。

捕获 d'écran 2021-04-17 至 21.35.26

在为我们的数据编写一些方法之前,让我们跳转到main.go文件并初始化与数据库的连接。

捕获 d'écran 2021-04-17 à 21.48.00

让我们奔跑吧go run main.go

捕获 d'écran 2021-04-17 至 21.50.25

数据库已配置但尚未完全完成,因为我想实现一些方法(如 CreatePost 和 GetPosts),但为此我们首先需要一个Post模型。

模型

继续在app包中创建一个新的包models,并创建一个文件。在文件里面,我们将创建一个包含 4 个字段的Post结构体。post.go

捕获 d'écran 2021-04-17 至 22.02.41

由于这是一个 REST API,我们稍后会将响应映射到 JSON,有时数据库中的字段可能与 JSON 字段不对应,或者我们可能希望灵活地添加新字段或删除字段。
为此,我们先在文件中创建一个JsonPost结构体。

捕获 d'écran 2021-04-17 至 22.06.21

最后我想在这个文件中添加的内容几秒钟后就会用到。当我们将帖子添加到数据库时,ID 会自动递增,这意味着我们在创建新帖子的请求时无需传递 ID。因此,让我们为此创建一个PostRequest结构体。

捕获 d'écran 2021-04-17 至 22.12.10

回到我们文件中的数据库,我想向我的PostDBdb.go接口添加 2 个方法GetPostsCreatePost

注意:我不会实现所有的 REST 动词端点(尽量保持简短),只是简单的 GET 和 POST。

捕获 d'écran 2021-04-17 至 22.17.10

在我们的文件中,我想为我的CreatePostschemas.go方法添加一个简单的insertPostSchema

捕获 d'écran 2021-04-17 至 22.58.42

让我们创建一个methods.go文件并编写我们的方法。

捕获 d'écran 2021-04-17 至 22.22.10

Http 处理程序

现在我们已经有了与数据库交互的所有方法,让我们像之前为IndexHandler编写 http 处理程序一样。在我们的handlers.go文件中,让我们从CreatePostHandler开始。

我们要做的是初始化一个空的PostRequest结构体,然后解析用户输入的请求体到该结构体中。为了解析或映射请求体,我将编写一个名为parse的辅助函数,并将其放入一个helpers.go文件中。

捕获 d'écran 2021-04-17 至 22.32.16

捕获 d'écran 2021-04-17 à 22.34.00

再次强调,这是一个REST API,因此发送 http 状态是个好习惯。我们接下来会发送很多带有 http 状态的响应,所以我会在文件中为此编写另一个辅助函数,helpers.go用于发送带有状态的 JSON 响应。

捕获 d'écran 2021-04-17 至 22.38.57

捕获 d'écran 2021-04-17 至 22.39.33

顺便说一下,还记得我们之前有个JsonPost结构体,方便我们灵活使用吗?我们最后添加一个辅助函数 ( helpers.go),用来将数据映射到该结构体。

捕获 d'écran 2021-04-17 至 22.45.26

继续使用CreatePostHandler,现在我们已经解析了请求主体,我们需要使用该数据来创建新帖子并将其保存在我们的数据库中。

捕获 d'écran 2021-04-17 至 22.56.09

现在要完成CreatePostHandler,我们只需要在我们的文件中的func initRoutesapp.go中创建一个新路由并调用我们的处理程序。

捕获 d'écran 2021-04-17 至 22.53.01

再次运行并让我们在Insomniago run main.go上进行测试

捕获 d'écran 2021-04-17 至 23.04.22

似乎有效👍🏻

在进行测试之前,让我们先实现更简单的GetPostHandler 。

捕获 d'écran 2021-04-17 至 23.14.36

捕获 d'écran 2021-04-17 至 23.17.28

重新启动应用程序
捕获 d'écran 2021-04-17 至 23.18.28

失眠测试
捕获 d'écran 2021-04-17 至 23.19.25

完美,一切正常 🙂

测试

测试代码也是非常好的做法,因此我们需要尝试为应用添加测试覆盖率。为此,您可以创建一个测试包,并添加要测试的测试文件,例如handler_test.godb_test.go

捕获 d'écran 2021-04-17 至 23.23.39

我实际上制作了一个视频并写了一篇关于在 Golang 中实现测试的文章,所以你可以查看一下 🙂

结论

就这样!这篇文章就写到这里吧,我知道还有改进的空间,但我想长话短说,只谈一下基础。

与往常一样,不要犹豫给我反馈,当今开发人员的角色是不断改进,这就是我想要做的🙂

请随时查看我的Youtube 频道,您也可以通过我的Twitter 帐户联系我,当然我会链接本文的GitHub 存储库。

很快再见!👋🏻

文章来源:https://dev.to/lucasnevespereira/write-a-rest-api-in-golang-following-best-practices-pe9
PREV
使用 NodeJS + Strapi 在 5 分钟或更短的时间内构建完整的 API(太棒了!)
NEXT
不要在前端这样做,否则……开发人员的前端良好实践