golang api项目

在上一篇文章中,我解释了为REST API设置GO应用程序的基础。 现在,我将通过首先创建可配置服务器,添加http路由器(mux)和一些数据库交互来详细介绍。 让我们开始( 室内聚会)吧!

该应用程序现在在docker中运行,可以响应代码更改并重新加载以获得即时反馈。 为了处理http请求,我将添加另一个依赖项,即http路由器(mux)。 您可以在此处了解更多信息。

这是一款轻巧,高性能的HTTP请求路由器,易于使用,并且具有大多数api所需的一切。

$ go get -u github.com/julienschmidt/httprouter

是时候创建服务器了。 我将其放置在pkg /目录中,因为它可能被重用:

package serverimport ("errors""log""net/http""github.com/julienschmidt/httprouter"
)type Server struct {srv *http.Server
}func Get () * Server {return &Server{srv: &http.Server{},}
}func (s *Server) WithAddr (addr string ) * Server {s.srv.Addr = addrreturn s
}func (s *Server) WithErrLogger (l *log.Logger) * Server {s.srv.ErrorLog = lreturn s
}func (s *Server) WithRouter (router *httprouter.Router) * Server {s.srv.Handler = routerreturn s
}func (s *Server) Start () error {if len (s.srv.Addr) == 0 {return errors.New( "Server missing address" )}if s.srv.Handler == nil {return errors.New( "Server missing handler" )}return s.srv.ListenAndServe()
}func (s *Server) Close () error {return s.srv.Close()
}

像往常一样, Get 函数返回指向我们服务器实例的指针,该实例公开了一些很容易解释的公共方法。 当我将此服务器放在主程序中时,它将变得更加明显。

服务器将需要路由和处理程序与外界进行通信。 接下来,我将其添加:

// cmd/api/router/router.gopackage routerimport ("github.com/boilerplate/cmd/api/handlers/getuser""github.com/boilerplate/pkg/application""github.com/julienschmidt/httprouter"
)func Get (app *application.Application) * httprouter . Router {mux := httprouter.New()mux.GET( "/users" , getuser.Do(app))return mux
}

// cmd/api/handlers/getuser/getuser.gopackage getuserimport ("fmt""net/http""github.com/boilerplate/pkg/application""github.com/julienschmidt/httprouter"
)func Do (app *application.Application) httprouter . Handle {return func (w http.ResponseWriter, r *http.Request, ps httprouter.Params) {fmt.Fprintf(w, "hello" )}
}

我通过显式传递应用程序配置在router.go定义我的所有路由并调用处理程序,以便每个处理程序都可以访问数据库,使用env vars进行配置等内容。

我将处理程序与路由器分开,并将它们分组在子文件夹cmd/api/handlers/{handlerName} 。 原因之一是处理程序将具有相应的测试文件。 它还将具有多个中间件文件,这些中间件文件还将具有测试,并且可能有很多处理程序。 如果分组不正确,它会很快失控。

现在有更多的构建块:服务器,路由器,记录器。 让我们在主程序中组装它们:

// cmd/api/main.gopackage mainimport ("github.com/boilerplate/cmd/api/router""github.com/boilerplate/pkg/application""github.com/boilerplate/pkg/exithandler""github.com/boilerplate/pkg/logger""github.com/boilerplate/pkg/server""github.com/joho/godotenv"
)func main () {if err := godotenv.Load(); err != nil {logger.Info.Println( "failed to load env vars" )}app, err := application.Get()if err != nil {logger.Error.Fatal(err.Error())}srv := server.Get().WithAddr(app.Cfg.GetAPIPort()).WithRouter(router.Get(app)).WithErrLogger(logger.Error)go func () {logger.Info.Printf( "starting server at %s" , app.Cfg.GetAPIPort())if err := srv.Start(); err != nil {logger.Error.Fatal(err.Error())}}()exithandler.Init( func () {if err := srv.Close(); err != nil {logger.Error.Println(err.Error())}if err := app.DB.Close(); err != nil {logger.Error.Println(err.Error())}})
}

要提及的新事物是,我通过链接方法调用和在实例上设置属性来组装服务器。 一件有趣的事情是WithErrLogger(logger.Error) ,它只是指示服务器使用我的自定义记录器来保持一致性。

我在单独的go例程中启动服务器,以便exithandler仍然可以运行并优雅地处理程序关闭。 pkg/logger包含2个标准库Logger的实例。 信息是打印出消息os.Stdout错误os.Stderr 。 我本可以使用logrus等花哨的记录器,但我打算使其保持简单。

接下来,让我们照顾数据库。 我使用用GO编写的迁移工具,可以用作CLI或库。 您可以阅读有关它的更多信息,并在此处找到安装说明。 安装后,让我们创建一些迁移文件。 从上面可以看出,我将在/users资源上进行操作,因此自然而然地会有users表:

$ migrate create -ext sql -dir ./db/migrations create_user

这将产生2个迁移文件在db/migrations向上向下的用户表。 所有文件都是空的,因此我们添加一些sql。

向上:

-- db/migrations/${timestamp}_create_user.up.sql
CREATE TABLE IF NOT EXISTS public.users
(id SERIAL PRIMARY KEY ,username VARCHAR ( 100 ) NOT NULL UNIQUE
);

向下:

-- db/migrations/${timestamp}_create_user.down.sql
DROP TABLE public.users

很简单,但是应该这样,对吧? 在运行迁移之前,让我们使用golang-migrate库并创建一个程序来简化此过程。 这也将在CI / CD管道中很好地工作,因为它将使我们跳过golang-migrate cli的安装, golang-migrate是管道构建的一个单独步骤。 为此,我将添加另一个依赖项:

$go get - u github. com /golang-migrate/migrate/v4

我将程序dbmigrate

// cmd/dbmigrate/main.go package mainimport ("log""github.com/boilerplate/pkg/config""github.com/golang-migrate/migrate/v4"_ "github.com/golang-migrate/migrate/v4/database/postgres"_ "github.com/golang-migrate/migrate/v4/source/file""github.com/joho/godotenv"
)func main () {godotenv.Load()cfg := config.Get()direction := cfg.GetMigration()if direction != "down" && direction != "up" {log.Fatal( "-migrate accepts [up, down] values only" )}m, err := migrate.New( "file://db/migrations" , cfg.GetDBConnStr())if err != nil {log.Fatal(err)}if direction == "up" {if err := m.Up(); err != nil {log.Fatal(err)}}if direction == "down" {if err := m.Down(); err != nil {log.Fatal(err)}}
}

快速概览这里发生的事情。 首先,我加载env vars。 然后,我得到指向config实例的指针,这将使我可以通过一些辅助方法轻松访问所需的所有var。 您可能已经注意到,这里有一个新的GetMigration方法。 它只会返回updown字符串来指示我的程序是否应该向上或向下迁移数据库。 您可以在此处查看最新更改。

现在,由于我已经安装了此工具,因此可以使用它。 我找到的最佳位置是scripts/entripoint.dev.sh 。在那里运行它可以避免常见的“哦,我忘了运行迁移”问题。 更新版本的entrypoint.dev.sh

#!/bin/bash
set -ego run cmd/dbmigrate/main.gogo run cmd/dbmigrate/main.go -dbname=boilerplatetestGO111MODULE=off go get github.com/githubnemo/CompileDaemonCompileDaemon --build= "go build -o main cmd/api/main.go" -- command =./main

这里发生了什么事? 第一次运行dbmigrate将使用.env文件中的所有默认值,因此它将对boilerplate数据库运行迁移。 在第二次运行中,我传递了-dbname=boilerplatetest以便它执行相同的操作,但针对boilerplatetest db。 接下来,我将以干净状态启动我的应用程序:

# remove all containers
docker container rm -f $(docker container ps -a -q)# clear volumes
docker volume prune -f# start app
docker-compose up --build

如果上面的所有工作过,我们应该看到users在这两个表boilerplateboilerplatetest数据库。 让我们检查一下:

# connect to pg docker container
docker exec -it $(docker ps --filter name=pg --format "{{.Names}}" ) /bin/bash# launch psql cli
psql -U postgres -W# ensure both DBs still present
\l# connect to boilerplate database and list tables
\c boilerplate
\dt# do same for boilerplatetest
\c boilerplatetest
\dt# in both databases you should see users table

这是运行以上命令时看到的:

可以肯定,一切都如预期。 现在,如果我们在Docker中运行应用程序时添加新的迁移该怎么办。 我敢肯定,停止docker-compose并再次重新运行命令以进行更改不是很方便。 好了, dbmigrate程序能够处理这种情况。 在新的终端标签中:

# migrate boilerplatetest db down
go run cmd/dbmigrate/main.go \-migrate=down \-dbname=boilerplatetest \-dbhost=localhost# you can now repeat steps from above to connect to pg container
# and ensure that users table is missing from boilerplatetest DB.# now bring it back up
go run cmd/dbmigrate/main.go \-migrate=up \-dbname=boilerplatetest \-dbhost=localhost

这里要提到的一件事是-dbhost=localhost 。 这是因为我们从主机连接到pg容器。 在docker-compose中,我们可以通过服务名称pg来引用相同的容器,但是我们不能从主机执行相同的操作。

希望您学到了一些有用的东西。 在第3部分中,我将为用户资源进行简单的CRUD操作。 它将包括中间件使用,验证等。 您还可以在此处查看整个项目并跟踪进度。 注意安全!

翻译自: https://hackernoon.com/how-to-create-golang-rest-api-project-layout-configuration-part-2-wh2z3y5z

golang api项目

golang api项目_如何创建Golang REST API:项目布局配置[第2部分]相关推荐

  1. 【ASP.NET Web API教程】2 创建各种Web API

    原文 [ASP.NET Web API教程]2 创建各种Web API Chapter 2: Creating Web APIs 第2章 创建各种Web API 本文引自:http://www.asp ...

  2. golang微信机器人_如何使用Golang从头开始创建Twitter机器人

    golang微信机器人 by Kofo Okesola 由Kofo Okesola 如何使用Golang从头开始创建Twitter机器人 (How to create a Twitter bot fr ...

  3. golang interface 类型转换_无符号Golang程序逆向方法解析

    在去年的inctf2018中,出现了一道Go语言编写的进程通信逆向题,无论是从题目整体设计还是解题思路上来说都独树一帜,自己在解题过程中遇到了很多问题,但我这不打算做过多探讨,网上也有大佬的解题过程, ...

  4. 如何从数据库中筛选出达成指定里程碑节点的项目_公测首发 | 支持API的连接型智能多维表格,「vika维格表」如何让数字化真正成为生产力?...

    △ 是新朋友吗?记得先点上面 关注我哦~ 维格星球 http://vika.cn 市面上的软件工具那么多,但却很少可以做好连接和整合,真正帮助我们更好地工作和生活. 毕竟,对于使用软件提升「生产力」, ...

  5. 数据科学项目_完整的数据科学组合项目

    数据科学项目 In this article, I would like to showcase what might be my simplest data science project ever ...

  6. tia v15 添加项目_作为一名机器人集成项目的电气工程师,你及格吗?

    职场有风险,入行需谨慎.每个行业光鲜的背后都会存在弊端,只是有的行业更为辛苦.道路不止一条,你可以尝试新的选择,也可以迎难而上坚持下去.对于刚接触机器人自动化的小伙伴,肯定想早日成为一名合格的工程师. ...

  7. 简单有趣的web项目_有趣而简单的电子项目书

    简单有趣的web项目 "当您去商店购买电子小物件时,您会想到自己可以自己做一个吗?或者甚至可以自己做一个有趣的事情?" 这就是约翰·贝希塔尔(John Baichtal)的面向初学 ...

  8. github上 开源项目_在GitHub上组织开源项目的工作流程的3个技巧

    github上 开源项目 管理开源项目是一项艰巨的工作,挑战随着项目的发展而增长. 最终,一个项目可能需要满足不同的需求并跨越多个存储库. 这些问题不是技术问题,但对于解决扩展技术项目很重要. 诸如敏 ...

  9. Qt创建项目:手把手创建第一个Qt项目

    上一节介绍了QtCreator编辑器的页面长什么样子,以及都有哪些功能区,每个功能区都是用来做什么的.这一节我就手把手带大家创建一个Qt项目. 创建项目 点击新建按钮 创建项目有两个入口,一个是在欢迎 ...

  10. java从github下载项目_在github下载的java项目通过idea打开(全流程图文,傻瓜式)

    今天从github把我以前写的一个小demo下载下来了,第一次下载项目,摸索了一个多小时,才运行起来. 下载有两种方法,通过git下载,或者直接压缩包下载,我选的时压缩包下载(因为还没学会git下载 ...

最新文章

  1. [解决]Win7 操作系统不能安装VMware
  2. 火狐表格错乱兼容性问题
  3. PyTorch 1.0 中文官方教程:什么是 PyTorch
  4. 毕设日志——配置服务器与测试gpu版本的tf faster rcnn代码
  5. MQTT工作笔记0007---剩余长度
  6. 解决Ubuntu刚装好的时候su命令密码错误的问题
  7. 帆软连接kingbase8
  8. linux专业画图工具astah下载和安装
  9. 数学符号——指示函数(样子像空心的1的一个数学符号)
  10. php个人发卡搭建教程,个人发卡平台ZFAKA程序搭建详细教程
  11. Jquery 调用 浏览器打印机
  12. 原型模式与深拷贝浅拷贝
  13. Elasticsearch-好文推荐
  14. 【机器学习】贝叶斯分类三大实战项目:高斯模型进行疾病诊断、多项式模型进行文本分类、伯努利模型进行好/差评判别
  15. SpringBoot自动生成接口文档
  16. 触宝科技sp专场面试复盘
  17. ip helper-address原理
  18. C#三十五 三层架构企业应用
  19. 最新的Android版本是什么? 以及如何更新到当前的Android操作系统?
  20. SEO META 优化

热门文章

  1. TDSQL的2020进化在未来之前,更在未来之后
  2. 一些Linux常见发行版本
  3. pyinstaller 打包python qyqt5 成exe
  4. 跟波哥学习php之会话管理图片上传验证码(第五季)-lampol-专题视频课程
  5. 哪个服务器可以做展示型网站,企业网站的五种类型你都知道哪些?
  6. 系统架构合理性的思考 | 京东云技术团队
  7. 语料库技术与应用—基于维基百科构建日语平行语料并爬取谷歌翻译语音(mp3)
  8. 宝宝换季就生病,可能是家长保护得太好了
  9. Android 实战项目:找回密码
  10. 只用html+css做出会跳动爱心