golang 读一行

If you like to understand know why we choose golang in the first as an alternative to python, see https://medium.com/@anil.k.nayak8/gopher-in-healthifyme-25eb8494305b

In this article I would like to outline the main points we had in mind while creating an application using golang, the problems encountered and some of the packages that helped us. We created a simple microservice that sat on top of multiple databases and acted as a security/filtering layer.

在本文中,我想概述在使用golang创建应用程序时要记住的要点,遇到的问题以及一些对我们有帮助的软件包。 我们创建了一个简单的微服务,它位于多个数据库之上,并充当安全/过滤层。

We knew what we had to do: Create a JSON rpc server that would be consumed mainly by our python clients. But golang does not have a framework like Django or Ruby on Rails, which means there are no standards set on how things are to be done.

我们知道我们要做的事情:创建一个主要由python客户端使用的JSON rpc服务器。 但是golang没有像Django或Ruby on Rails这样的框架,这意味着没有关于如何完成事情的标准。

We had to make all decisions based on the project we were doing combined with the experince we had with python. So we made a note of all the things we needed to clear before going ahead:

我们必须根据正在执行的项目以及结合python的经验来做出所有决策。 因此,我们记录了在继续操作之前需要清除的所有内容:

  • Folder structure资料夹结构
  • Logging Setup记录设定
  • Configuration with different environments with different sources of info like file, env etc使用不同的环境配置不同的信息源,例如文件,环境等
  • Connecting to database and executing queries.连接到数据库并执行查询。
  • Setting up rpc设置rpc
  • Writing tests编写测试

Deciding the folder structure

确定文件夹结构

This was difficult at the beginning of a new project. So we took inspiration from https://github.com/golang-standards/project-layout and modified it a bit to suit our needs. We are now using the new go modules and they’re amazing! We can easily manage the dependencies with go plugins for IDEs. Go will automatically take care of dependencies and their versions. The only thing we should attend to is importing the third party module as url.

在新项目开始时这很困难。 因此,我们从https://github.com/golang-standards/project-layout获得了灵感,并对其进行了一些修改以满足我们的需求。 我们现在正在使用新的go模块,它们很棒! 我们可以使用IDE的go插件轻松管理依赖项。 Go将自动处理依赖项及其版本。 我们唯一需要注意的是将第三方模块作为url导入。

The following is the folder structure we are using:

以下是我们正在使用的文件夹结构:

build: development and production binaries.

build :开发和生产二进制文件。

cmd: the main go file. Ends up being lean as most of the initialization work happens here.

cmd:主要的go文件。 最终变得精益,因为大多数初始化工作都在这里进行。

config: responsible for the configuration of the application. All the packages that need the current configuration will be in connection with this file.

config:负责应用程序的配置。 需要当前配置的所有软件包都将与此文件关联。

pkg: contains all individual packages which can depend on each other.

pkg:包含可以相互依赖的所有单个软件包。

Logging Setup

记录设定

Golang comes with a very handy logging package.However we had debates on whether the native package should be used or the popular package ‘logrus’ or create a new custom interface all together. Logrus is an extension of the interface for the native logging package. Lorgus won as it was just what we needed, with all methods like Print, Debug, Panic etc. We could also change the logging Output.

Golang附带了一个非常方便的日志记录程序包,但是我们对于是否应使用本机程序包还是流行的程序包'logrus'或共同创建一个新的自定义接口存在争议。 Logrus是本机日志记录程序包的接口的扩展。 Lorgus赢得了我们所需要的,它使用了诸如Print,Debug,Panic等所有方法。我们还可以更改日志记录Output。

We created a logger package in common that exposes an instance of logrus. And the same is used everywhere.

我们共同创建了一个记录器包,该记录器包公开了logrus的一个实例。 到处都使用相同的方法。

The final code was very simple:

最终代码非常简单:

var Log *logrus.Logger = logrus.New()

var Log * logrus.Logger = logrus.New()

And for any logging:

对于任何日志记录:

logger.Log.Debug(“I am a debug message”)

logger.Log.Debug(“我是调试消息”)

Setup Configuration

设定设定

Here we had to evaluate multiple factors. We had two options: either use a third party package or create our own configuration package. If we choose a third party, which one?

在这里,我们必须评估多个因素。 我们有两个选择:使用第三方程序包或创建我们自己的配置程序包。 如果我们选择第三方,哪一个?

So we asked ourselves: what do we need from the package?

因此,我们问自己:包装中需要什么?

It should be able to read from a file like json/yaml. Since we needed sensitive information like database user, database password etc from a secret manager, it also should be able to read from the environment. And finally, it should do both simultaneously. For example for a single struct DatabaseConfig, host can come from env and the database name can come from the config file based on the environment.

它应该能够从json / yaml这样的文件中读取。 由于我们需要来自机密管理器的敏感信息,例如数据库用户,数据库密码等,因此它也应该能够从环境中读取。 最后,它应该同时执行两个操作。 例如,对于单个结构DatabaseConfig,主机可以来自env,数据库名称可以来自基于环境的配置文件。

We evaluated the ability of a third party package viper to do the same. However it could not function with multiple sources at the same time. So we tried a different package cleanenv. Bingo! It had all the features we needed.

我们评估了第三方包装毒蛇执行此操作的能力。 但是,它不能同时与多个源一起使用。 因此,我们尝试了不同的包cleanenv。 答对了! 它具有我们需要的所有功能。

A sample code would look something like:

示例代码如下所示:

Here we specify that the yaml file can be taken on preference, but it will fallback to env if the key is not available in the yaml file.

在这里,我们指定可以优先使用yaml文件,但是如果密钥在yaml文件中不可用,它将回退到env。

Database Connection and Querying

数据库连接和查询

There are tons of libraries available for database interaction for go and each one has its own flavour. An added advantage here is that golang comes with a sql interface by default and most of the libraries implement the same. So now it’s easier to switch.

有大量库可供进行go的数据库交互,每个库都有自己的特色。 此处的另一个好处是,默认情况下,golang带有sql接口,并且大多数库都实现了该接口。 因此,现在切换起来更加容易。

Initially we went with the native sql package to create database connections and execute queries. But it seemed very basic. Inorder to execute each and every query and convert into a struct, each column needs to be scanned, which would look like a whole lot of boilerplate code.

最初,我们使用本地sql包创建数据库连接并执行查询。 但这似乎很基本。 为了执行每个查询并转换为结构,需要扫描每一列,这看起来像是很多样板代码。

For example: suppose you are trying to select a row with 4 columns

例如:假设您正在尝试选择4列的行

This whole process has to be done for each db query.

必须为每个数据库查询完成整个过程。

This is where sqlx [github.com/jmoiron/sqlx] comes into the picture.It has a feature which will directly take the struct and do the scanning for us. It also gives an interface to specify what the db column names mapped to each struct field. The below example specifies the same:

这就是sqlx [ github.com/jmoiron/sqlx ]出现的地方。它具有一个功能,可以直接获取struct并为我们进行扫描。 它还提供了一个接口,用于指定映射到每个struct字段的数据库列名称。 下面的示例指定相同的内容:

And now it’s simple! Bonus: this package comes with an optional sql interface!

现在很简单! 奖励:该软件包带有可选的sql接口!

Setting up RPC

设置RPC

Golang comes with its own json rpc package. So RPC setup can be very simple.

Golang带有自己的json rpc软件包。 因此,RPC设置非常简单。

But there is a glitch: it works on a TCP layer and it would make sense to write the rpc client also in golang. But our client is written in python. Hence using a tcp layer and maintaining consistent connection can create problems.

但是有一个小故障:它可以在TCP层上工作,并且也可以在golang中编写rpc客户端。 但是我们的客户端是用python编写的。 因此,使用tcp层并保持一致的连接会产生问题。

So we treated each rpc request as an independent http request.

因此,我们将每个rpc请求都视为一个独立的http请求。

So now, we used 2 packages github.com/gorilla/rpc/v2 and github.com/gorilla/rpc/v2/json.

所以现在,我们使用了2个软件包github.com/gorilla/rpc/v2和github.com/gorilla/rpc/v2/json。

Using this we could create a simple endpoint for example ‘/json’ and mount our RPC server on it.

使用这个我们可以创建一个简单的端点,例如'/ json',然后在上面安装我们的RPC服务器。

The sample code would look something like:

示例代码如下所示:

We can also add different endpoints to handle different kinds of requests. Becomes handy when adding a healthcheck route. Any client would be able to use it as it is very flexible.

我们还可以添加不同的端点来处理不同类型的请求。 添加健康检查路线时变得很方便。 任何客户端都可以使用它,因为它非常灵活。

Setting up Tests.

设置测试。

Golang comes with its own test system. Great! Now we don’t have to use external setups unless absolutely necessary.

Golang带有自己的测试系统。 大! 现在,除非绝对必要,否则我们不必使用外部设置。

Since we are dealing with different databases and executing queries, we need a proper system where we can mock the database interaction. All we need to have is some struct, that has the same interface as the database object. We also need to have a global database instance which can be replaced by the mock database instance. Thus, we can mock all the database interactions and test different cases out.

由于我们要处理不同的数据库并执行查询,因此需要一个合适的系统来模拟数据库交互。 我们需要的只是一些结构,该结构具有与数据库对象相同的接口。 我们还需要有一个可以由模拟数据库实例替换的全局数据库实例。 因此,我们可以模拟所有数据库交互并测试不同的情况。

We used two different packages to do this.

我们使用了两个不同的程序包来做到这一点。

  1. github.com/DATA-DOG/go-sqlmock which creates a mock database based on sql.

    github.com/DATA-DOG/go-sqlmock ,它基于sql创建一个模拟数据库。

2. github.com/jmoiron/sqlx which has the feature to create a database having the same interface as sqlx from other database instances. This is extremely useful as we use sqlx to interact with databases.

2. github.com/jmoiron/sqlx ,具有从其他数据库实例创建与sqlx具有相同接口的数据库的功能。 当我们使用sqlx与数据库进行交互时,这非常有用。

And now the final step: replace our global database instance with the mock database we created. We wrapped this behaviour in a single function and used it in all our testing methods. This made sure that we have a new fresh database for each test.

现在是最后一步:用我们创建的模拟数据库替换全局数据库实例。 我们将此行为包装在一个函数中,并在所有测试方法中使用了它。 这确保了每个测试都有一个新的新数据库。

Now the sample code looks like:.

现在,示例代码如下:

Handling Errors

处理错误

Golang gives no special status to errors. Error is treated as a normal value, just like any other interface. Now it is very important that all kinds of errors are handled.

Golang没有为错误赋予特殊的状态。 就像任何其他接口一样,错误被视为正常值。 现在,处理各种错误非常重要。

If any error is left out it can crash production. Fortunately there is a package to check if any errors are missed.https://github.com/kisielk/errcheck helps in finding error cases which should have been checked but has been left out. We also needed to make sure the errors have contextual information. For e.g a rpc can fail due to several reasons: database connection error, query execution error, rows scanning error etc. The client that uses a function to execute a database query needs more meta information, including the error trace to understand the error in detail. For this we have used the package “github.com/pkg/errors” which helps in wrapping an error with additional parameters. E.g: errors.Wrap(err, “Error in statement execution”). This become handy while debugging.

如果遗漏任何错误,可能会导致生产崩溃。 幸运的是,有一个软件包可以检查是否遗漏了任何错误。 https://github.com/kisielk/errcheck帮助查找应该检查但已排除的错误情况。 我们还需要确保错误具有上下文信息。 例如,rpc可能由于以下几个原因而失败:数据库连接错误,查询执行错误,行扫描错误等。使用函数执行数据库查询的客户端需要更多元信息,包括错误跟踪以详细了解错误。 为此,我们使用了软件包“ github.com/pkg/errors ”,该软件包有助于使用其他参数包装错误。 例如:errors.Wrap(err,“语句执行中的错误”)。 这在调试时变得很方便。

Bonus lessons from our experience:

我们的经验教训:

  1. Not to use the ‘init’ feature unless absolutely necessary. The dependency system might break as there is no way of knowing which package will run first. This will also cause problems while writing tests.除非绝对必要,否则请勿使用“初始化”功能。 依赖系统可能会中断,因为无法知道哪个程序包将首先运行。 这也会在编写测试时引起问题。
  2. Not to use Panic unless the application cannot run when the error occurs. Always try to handle errors gracefully.除非错误发生时应用程序无法运行,否则不要使用Panic。 始终尝试优雅地处理错误。
  3. Always wrap errors to give them more meta information.总是包装错误以给他们更多的元信息。
  4. Always defer to cleanups like closing database connection, closing a file etc.始终遵循清理操作,例如关闭数据库连接,关闭文件等。
  5. Keep interfaces as lean as possible. This would bring out the most from golang’s powerful interface concept.保持接口尽可能紧凑。 这将充分利用golang强大的界面概念。

Conclusion.

结论。

Though a low level one, Go is a great language. Unlike others of its kind, memory management is very flexible. It has a proper way to format code. Gofmt does all the work and kind of universally accepted*. The type system is also simple. The code we write becomes very clear and understandable with very little effort. Most importantly, it creates a single binary. It can run anywhere* with no setup and no dependencies. Also the compiler is superfast with a great IDE support. When we created a build using docker to deploy the docker image to production size, it was just 8MB, a very small size and hence easy to handle.

尽管是一个较低级别的语言,但Go是一门很棒的语言。 与同类产品不同,内存管理非常灵活。 它具有格式化代码的正确方法。 Gofmt可以完成所有工作,并且被广泛接受*。 类型系统也很简单。 我们编写的代码变得非常清晰和易于理解。 最重要的是,它创建了一个二进制文件。 它可以在任何地方运行*,而无需设置和依赖。 而且,编译器超快,并具有强大的IDE支持。 当我们使用docker创建一个构建以将docker映像部署到生产大小时,它只有8MB,非常小,因此易于处理。

However there is no proper standard for code organisation yet, maturity of different third party packages etc. But there is hope it will become the next go to language for server side development once it establishes its ground. It was worth while experimenting in golang and we will definitely extend its use for new projects and in some of our older projects as well.

但是,尚无适当的代码组织标准,不同的第三方软件包的成熟度等。但是,一旦它奠定了基础,就有望成为服务器端开发的下一代语言。 在golang上进行实验是值得的,我们一定会在新项目和某些旧项目中扩展它的用途。

翻译自: https://medium.com/healthify-tech/working-with-golang-our-first-steps-34dc38a2ee92

golang 读一行


http://www.taodudu.cc/news/show-4555090.html

相关文章:

  • GoLang之图解channel之读、写、关闭
  • golang常用库之-文件操作(os、path、filepath、ioutil包)、Go 读文件、Go 写文件
  • Go语言bufio包(读与写)
  • go语言读文件
  • 学习 Go 语言(Golang)读书笔记
  • Go 文件操作(创建、打开、读、写)
  • 超全总结:Go 读文件的 10 种方法
  • 菜鸟
  • 走进中国8大菜系之——徽菜
  • 05.OpenWrt-写入mac地址
  • openwrt中br-lan,eth0,eth0.1,eth0.2 已经 实际网口wan,lan对应的配置
  • 05.局域网_NAT
  • 重新整理Mybatis-05
  • CISSP笔记05
  • 斐讯的服务器不稳定,K1不稳定的原因找到了!原因是CPU时钟频率太高,要降频!...
  • python05元组字典
  • 阿里LinkWAN SDK使用之mqtt数据流
  • openwrt修改lan口地址失败_wr703n 刷openwrt 网口是lan口,怎样改成wan口?
  • 【接口篇 / Wan】(7.0) ❀ 05. 将 4G 作为备用宽带使用 ❀ FortiGate 防火墙
  • 开源会是SD-WAN的发展方向吗?
  • 05 友元
  • CCNA WAN IPv6
  • Cisco Viptela SD-WAN 基本部署
  • WAN LAN WLAN区别
  • 教程篇(6.4) 05. 集成 ❀ SD-WAN ❀ Fortinet 网络安全架构师 NSE7
  • SD-WAN,让你的组网更灵活
  • 学位论文写作的正确打开方式:程序员的理性与倔强
  • python的论文图表_干货丨史上最全的论文图表基本规范
  • 如何提升论文写作能力?
  • 科研中常用的计算机应用软件,研究生的日常软件(文献类软件使用介绍及心得)...

golang 读一行_与golang合作的第一步相关推荐

  1. golang底层深入_带有Golang的GraphQL:从基础到高级的深入研究

    golang底层深入 by Ridham Tarpara 由里德姆·塔帕拉(Ridham Tarpara) 带有Golang的GraphQL:从基础到高级的深入研究 (GraphQL with Gol ...

  2. golang反编译_【Golang】脱胎换骨的defer(一)

    Go语言的defer是一个很方便的机制,能够把某些函数调用推迟到当前函数返回前才实际执行.我们可以很方便的用defer关闭一个打开的文件.释放一个Redis连接,或者解锁一个Mutex.而且Go语言在 ...

  3. golang mysql加锁_使用golang实现类InnoDB数据行锁效果

    在关系型数据库领域,为人津津乐道的一个特性,便是数据库的锁设计及事务隔离级别. 本文通过golang系统库sync,来实现简单的数据库数据读写操作. 场景说明 小明经营一家水果店,创业初始资金为100 ...

  4. golang 包含 数组_在 Golang 中如何快速判断字符串是否在一个数组中

    在使用 Python 的时候,如果要判断一个字符串是否在另一个包含字符串的列表中,可以使用in 关键词,例如: name_list= ['pm', 'kingname', '青南'] if 'king ...

  5. golang mysql 崩溃_使用GoLang与mysql连接失败

    我试图使用Go语言连接MySql数据库并给我以下错误. sql: unknown driver "mysql" (forgotten import?) 我的守则 package m ...

  6. golang mysql封装_使用Golang 封装一个Api 框架 ----- 数据库操作篇(gorm引入)

    在models/baseModel 定义了 一个BaseModel对象,在这个对象上定义了 获取数据库连接和 释放数据库连接的方法 type BaseModel struct { dbConnect ...

  7. 如何用c++画图_画图教室 | 绘制Mapping第一步:美团搜索火锅串串香...认真的!...

    画图之前总要做好万全准备,收拾桌子.擦擦电脑.打开某黄色蓝色APP点个外卖...有人说这都是浪费时间拖延行为,今天小编要在此正名,起码点开外卖不是!! 看看这张汇集了成都火锅.串串.茶馆等美食大数据的 ...

  8. golang 读取文件最后一行_测试用例是开发人员最后一块遮羞布

    测试用例是开发人员最后一块遮羞布 最近一周写一个比较复杂的业务模块,越写到后面真心越心虚.操作越来越复杂了,代码也逐渐凌乱了起来.比如一个接口,传入的是一个比较复杂的大json,我需要解析这个大jso ...

  9. golang 加密文件_如何使用Go加密文件

    golang 加密文件 Cryptography is mandatory in the current modern world. In this era of big data and data ...

最新文章

  1. 博弈最高位POJ 1704(Georgia and Bob-Nim博弈)
  2. postman使用介绍
  3. 编程之美-电梯调度算法方法整理
  4. 【论文解读】AAAI21最佳论文Informer:效果远超Transformer的长序列预测神器!
  5. webpack常用的三种JS压缩插件
  6. 猎豹浏览器网页声音怎么关闭
  7. koa源码分析-generator和yield分析
  8. 机器学习入门06 - 训练集和测试集 (Training and Test Sets)
  9. ORACLE10g中 ora-12638:身份证明检索失败(
  10. 如何设置高度为1的分隔线
  11. 在Spring项目下集成CXF
  12. 用友u8不显示服务器名,用友u8提示对数据库服务器名
  13. 3D LUT调色预设如何导入并应用?(fcpx/PR/AE/PS/LR/达芬奇)
  14. 数据中心与灾备中心建设总结
  15. svn报错E175002
  16. 计算机打字练习程序,一个简单的打字练习程序
  17. 南邮计算机学院考研论坛,考南邮的心得,但愿对大家有所帮助!!!
  18. Android一些控件上显示的英文字母都被转为大写字母的原因分析及问题解决
  19. rust下沉试密室怎么用_魔兽7.1考古任务黑鸦堡垒密室在哪 钥匙使用消失二楼铁门怎么开...
  20. 微信公众号文章音视频下载的几种办法-涵盖PC端和手机端

热门文章

  1. 2021前端面试及答案---(全部涉及比较全)
  2. SQLServer日期函数及查询当日昨日本周本月本季度本年数据
  3. java qq协议 php_PHP使用SMTP协议发送邮件
  4. Spring框架技术总结(一),如何才能更容易拿到大厂Offer
  5. 华为手机如何调时间显示_华为手机照相有时间日期显示怎样设置
  6. 点餐系统服务器价格,点餐系统小程序报价
  7. Three.js学习笔记 – “我和小伙伴都惊呆了”的特效和Three.js初探(转)
  8. 服务器Networking Latency测试
  9. Eclipse安装SVN插件的几种方法
  10. 血族群机器人_【lay兴】 《Heartbeat》[上]古老血族 X 智能AI丨 Can you feel my heartbeat?...