![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
go
文章平均质量分 86
白如意i
一位工作多年的后端,分享一些技术经验。
展开
-
Go 使用 MongoDB
在 MongoDB 中存储的 JSON 文档叫 BSON,是以二进制形式存储的。Go 的 MongoDB 驱动有两个表示 BSON 数据的类型:D 类型和 Raw 类型。如果想要查询一个文档,同样需要提供一个 filter 文档来筛选,同时需要一个接收结果的指针。为了查询单个文档,可以使用。下面的例子中,我们在 Find 的时候同时指定了额外的一些选项,这里我们设置最多获取的记录数为 2。一旦你连接到了数据库,我们就可以开始添加或者操作数据库中的数据了。类型的参数来筛选数据库中特定的文档,然后更新它。原创 2024-05-10 10:32:40 · 1692 阅读 · 24 评论 -
Go 单元测试完全指南(一)- 基本测试流程
而 E2E 测试和集成测试,往往需要启动整个项目,然后需要真实用户进行手动操作,这样的测试成本高,速度慢,所以我们往往不会频繁地运行这样的测试。只有在项目的最后阶段,我们才会运行这样的测试。这不难理解,单元测试往往用来验证代码的最小单元,比如一个函数、一个方法,这样的测试我们一个命令就能跑完整个项目的单元测试,而且速度还很快,所以单元测试是我们最常用的测试方式。很遗憾的是,Go 的测试框架并没有直接提供这样的功能,但是我们可以通过 Go 的特性来实现这样的功能。我们可以看到,两个测试失败输出的报错行都是。原创 2024-05-10 10:31:53 · 3906 阅读 · 62 评论 -
如何在 Ubuntu 16.04 上为多个平台构建 Go 可执行文件
Go 编程语言配备了丰富的工具链,使得获取包和构建可执行文件变得非常容易。Go 最强大的特性之一是能够为任何 Go 支持的外部平台交叉构建可执行文件。这使得测试和包分发变得更加容易,因为您不需要访问特定平台就能为其分发您的包。在本教程中,您将使用 Go 的工具来从版本控制获取包并自动安装其可执行文件。然后,您将手动构建和安装可执行文件,以便熟悉该过程。接着,您将为不同架构构建一个可执行文件,并自动化构建过程以创建多个平台的可执行文件。原创 2024-04-10 00:30:00 · 1073 阅读 · 0 评论 -
如何构建和安装 Go 程序
到目前为止,在我们的《如何使用 Go 编程》系列中,您已经使用go run命令自动编译您的源代码并运行生成的可执行文件。虽然这个命令对于在命令行上测试代码很有用,但是要分发或部署应用程序,您需要将代码构建成一个可共享的二进制可执行文件,或者一个包含可以运行您的应用程序的机器字节码的单个文件。为此,您可以使用 Go 工具链来构建和安装您的程序。在 Go 中,将源代码转换为二进制可执行文件的过程称为构建。原创 2024-04-08 00:45:00 · 1106 阅读 · 0 评论 -
优化集中式日志记录的方法:添加 Logstash 过滤器
Logstash 是一个强大的工具,用于集中和分析日志,可以帮助提供环境概览,并识别服务器的问题。增加 ELK Stack(Elasticsearch、Logstash 和 Kibana)设置的有效性之一是通过收集重要的应用程序日志,并通过使用过滤器对日志数据进行结构化,以便数据可以被轻松分析和查询。我们将围绕“grok”模式构建我们的过滤器,以将日志中的数据解析为有用的信息片段。原创 2024-02-03 08:00:00 · 1088 阅读 · 0 评论 -
一文搞懂 Go 1.21 的日志标准库 - slog
定制默认Logger最直接的方法是利用方法,允许您用自定义的日志记录器替换默认的日志记录器。使用方法还会改变log包使用的默认log.Logger。这种行为允许利用旧log当您需要使用需要后者(例如)的 API 时,也可以使用方法将转换为log.Loggerlog/slogDEBUG(-4)INFO(0)WARN(4)和ERROR(8)。每个级别之间的间隔为 4,这是一个经过深思熟虑的设计决定,以适应具有自定义级别的日志方案。例如,您可以在INFO和WARN之间创建一个自定义级别,其值为1、2或3。原创 2024-02-03 08:00:00 · 1404 阅读 · 1 评论 -
一文搞懂 Golang 高性能日志库 - Zap
到目前为止,我们已经展示了如何通过 Zap 提供的生产和开发预设来使用默认配置。现在让我们来看看如何使用自定义配置选项创建一个实例。使用Zap创建自定义Logger有两种主要方法。第一种方法是使用其Configimport ("os""stderr",},"stderr",},},")上面的函数返回一个新的zap.Logger,它的功能类似于Logger,但有一些不同之处。我们将 Zap 的生产配置作为我们自定义日志记录器的基础,通过调用并稍微修改它,将ts字段更改为。原创 2024-02-02 08:00:00 · 2554 阅读 · 1 评论 -
gitlab ci cd 不完全指南
CI()持续集成,CD()持续部署(也包含了持续交付的意思)。lint检查,检查代码是否符合规范自动运行测试,检查代码是否能通过测试这个过程我们可以称之为 CI,也就是持续集成,这个过程是自动化的,也就是说我们不需要手动去执行这些操作,只需要提交代码,这些操作就会自动执行。CD 指的是在我们 CI 流程通过之后,将代码自动发布到服务器的过程,这个过程也是自动化的。在有了前面 CI 的一些操作之后,说明我们的代码是可以安全发布到服务器的,所以就可以进行发布的操作。原创 2024-02-02 08:00:00 · 3388 阅读 · 7 评论 -
cobra - 更容易地构建命令行应用
目前市面上许多的著名的 Go 语言开源项目都是使用 Cobra 来构建的,例如:K8s、Hugo、etcd、Docker 等,是非常可靠的一个开源项目。方法,该方法会返回带有指定名称和错误处理属性的空命令集给我们去使用,相当于就是创建了一个新的命令集去支持子命令了。方法实现了对命令行参数 name 的解析和绑定,其各个形参的含义分别为命令行标识位的名称、默认值、帮助信息。都写在一块不是一个好的实践,如果命令多的情况下,这个文件会非常大。方法,将命令行解析为定义的标志,便于我们后续的参数使用。原创 2024-02-01 08:00:00 · 639 阅读 · 0 评论 -
color - 让你的输出带点颜色
是一个可以让你输出带颜色文本的库。原创 2024-02-01 08:00:00 · 291 阅读 · 3 评论 -
spew - 更直观地打印变量
除了 spew,我们当然也可以直接选择通过 IDE 的 debug 功能来调试。原创 2024-01-31 08:00:00 · 267 阅读 · 0 评论 -
viper - go 配置管理
Viper 是适用于 Go 应用程序的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。设置默认值从 JSON、TOML、YAML、HCL、envfile 和 Java properties 格式的配置文件读取配置信息实时监控和重新读取配置文件(可选)从环境变量中读取从远程配置系统(etcd 或 Consul)读取并监控配置变化从命令行参数读取配置从 buffer 读取配置显式配置值。原创 2024-01-31 08:00:00 · 1247 阅读 · 12 评论 -
xdg - 获取 XDG 标准目录路径
golang xdg 库的基本使用原创 2024-01-30 08:00:00 · 635 阅读 · 0 评论 -
一文搞懂 Golang 高性能日志库 Zerolog
Zerolog是一个高性能、零内存分配的 Go 日志库。它为不需要垃圾回收的延迟敏感型应用程序提供结构化日志记录功能。您可以以完全零分配的方式使用,这样在初始化记录器对象后,堆上不会再分配其他对象,从而防止触发垃圾回收。本教程将解释如何在 Go 应用程序中安装、设置和使用 Zerolog 记录器。我们将首先介绍它的 API 和它提供的所有选项,并展示如何以各种方式自定义它们。最后,我们将描述如何在典型的 Web 应用程序中使用它,以便您可以很好地了解如何在您的项目中采用它。原创 2024-01-30 08:00:00 · 2629 阅读 · 0 评论 -
go map 设计与实现
map只是一个哈希表。数据被排列成一组bucket。每个bucket最多包含8个键/值对。哈希值的低位字节位用于选择bucket。每个bucket包含每个哈希的几个高位字节位(tophash),以区分单个桶中的条目。如果超过8个key哈希到同一个桶,我们将额外的桶以链表的方式起来。(解决哈希冲突,链表法)当哈希表扩容时,我们会分配一个两倍大的新bucket数组。然后bucket从旧bucket数组增量复制到新bucket数组。map迭代器遍历bucket。原创 2024-01-29 08:00:00 · 1086 阅读 · 0 评论 -
Go map 读写性能优化 - 分片 map
Go 的map设计上不支持并发读写,如果我们有并发读写操作会直接panic。Go 的设计者们认为,多数情况下,我们并不需要从多个 goroutine 来对map进行安全访问,所以他们没有在底层实现map的互斥操作。有两种方法可以解决map并发读写的问题:互斥锁、sync.Map。但是sync.Map设计上是应对某些特定场景的,并不合适所有场景。我们可以通过分片的方式来解决map并发读写的问题,这样可以减少锁的竞争,提高并发读写性能。目前已经有现成的开源库可以使用了。原创 2024-01-29 08:00:00 · 1253 阅读 · 0 评论 -
go mod 依赖管理
介绍 go mod 的基本用法、常见用途原创 2024-01-28 08:00:00 · 552 阅读 · 0 评论 -
Go MongoDB Driver 中的 A D M E 类型是什么
介绍 Go 的 mongodb 驱动中的几个类型的实际用途原创 2024-01-28 08:00:00 · 401 阅读 · 0 评论 -
Go MongoDB Driver 实例
介绍 Go 中 mongodb 的常见用法原创 2024-01-28 08:00:00 · 369 阅读 · 0 评论 -
go slice 扩容实现
go 的切片在容量较小的情况下,确实会进行2倍扩容,但是随着容量的增长,扩容的增长因子会逐渐降低。新版本的growslice实现中,只有容量小于256的时候才会进行2倍扩容,然后随着容量的增长,扩容的因子会逐渐降低(但并不是直接降到1.25,而是一个相对缓慢的下降)。原创 2024-01-27 08:00:00 · 1134 阅读 · 0 评论 -
go slice 基本用法
指定长度:不指定长度,由编译器推导出数组的长度:上面这两种定义方式都定义了一个长度为 3 的数组。正如我们所见,长度是数组的一部分,定义数组的时候长度已经确定下来了。切片的定义方式跟数组很像,只不过定义切片的时候不用指定长度在上面定义切片的代码中,我们可以看到其实跟数组唯一的区别就是少了个长度。那其实我们可以把切片看作是一个无限长度的数组。当然,实际上它并不是无限的,它只是在切片容纳不下新的元素的时候,会自动进行扩容,从而可以容纳更多的元素。原创 2024-01-27 08:00:00 · 1608 阅读 · 0 评论 -
go sync.Map 设计与实现
一顿源码看下来,我们不难发现,sync.Map的大部分方法整体处理流程上是非常相似的,都是先从read map中读取,如果没有找到,那么就需要加锁,然后做。如果还是没找到,那么就从dirty map中查找,如果还是没找到,那么就返回false。这样做的目的都是在尽量地减少锁的占用,从而获得更好的性能。同时,如果在dirty map中查找的次数多了,会触发dirty map转换为read map的操作流程,这样一来,下一次搜索同样的key就不再需要加锁了。最后一个关键的点是,在sync.Map。原创 2024-01-26 08:00:00 · 1320 阅读 · 0 评论 -
go sync.Pool 设计与实现
最后,我们将这一节的内容总结一下,可以得到下面这个图:go 进程内会有多个 P,每个 P 都会关联一个poolLocal。poolLocal中包含了一个和一个pad中包含了两个字段,private和shared。private是一个any类型的字段,用来存储我们调用Pool的Put方法的时候传入的数据,Get的时候如果private中有数据,那么就会直接返回private中的数据。shared是一个poolChain,用来存储我们调用Pool的Put方法的时候传入的数据,Get。原创 2024-01-26 08:00:00 · 2074 阅读 · 0 评论 -
Go type assertions
x.(T)含义:断言x不是nil并且存储的是T类型的值用途:检查x是否为nil检查x能否转换为类型T转换x为类型Tt := x.(T),返回一个类型为T的值,如果x为nil,产生 panic,如果x为nil或者不是T类型,ok的值为false,否则ok的值为true并且t是一个类型为T的值。原创 2024-01-25 08:00:00 · 376 阅读 · 0 评论 -
go validator 值为 0 required 验证
验证一些空值的时候,需要使用指针类型。字段传入了值,但是验证却不通过。在这个例子中,虽然我们的。原创 2024-01-25 08:00:00 · 547 阅读 · 0 评论 -
Go 使用 MongoDB
在 MongoDB 中存储的 JSON 文档叫 BSON,是以二进制形式存储的。Go 的 MongoDB 驱动有两个表示 BSON 数据的类型:D 类型和 Raw 类型。如果想要查询一个文档,同样需要提供一个 filter 文档来筛选,同时需要一个接收结果的指针。为了查询单个文档,可以使用。下面的例子中,我们在 Find 的时候同时指定了额外的一些选项,这里我们设置最多获取的记录数为 2。一旦你连接到了数据库,我们就可以开始添加或者操作数据库中的数据了。类型的参数来筛选数据库中特定的文档,然后更新它。原创 2024-01-25 08:00:00 · 1053 阅读 · 0 评论 -
go 依赖注入设计与实现
在现代的 web 框架里面,基本都有实现了依赖注入的功能,可以让我们很方便地对应用的依赖进行管理,同时免去在各个地方 new 对象的麻烦。比如Laravel里面的,又或者 Java 的Spring框架也自带依赖注入功能。今天我们来看看 go 里面实现依赖注入的一种方式,以inject库为例子(我们要了解一个软件的设计,先要看它定义了一个什么样的模型,但是在了解模型之前,我们更应该清楚了解,为什么会出现这个模型,也就是我们构建出了这个模型到底是为了解决什么问题。原创 2024-01-24 08:00:00 · 1028 阅读 · 0 评论 -
go 反射的常见用法
通过可以判断反射对象的类型,Kind涵盖了 go 中所有的基本类型,所以反射的时候判断Kind就足够了。如果要获取反射对象的值,需要传递指针给。可以往chan的反射对象中发送数据,也可以从chan的反射对象中接收数据。方法可以修改map中的元素。MapRange方法可以获取map的迭代器。可以通过Index方法获取slice的元素,也可以通过SetIndex方法修改slice的元素。可以通过SetString方法修改string的值。对于interface和Pointer。原创 2024-01-24 08:00:00 · 1225 阅读 · 0 评论 -
Go 等待协程完成
chanel 的特性是从 channel 中获取数据的时候会引起阻塞,直到 channel 有数据,所以我们可以利用这个特性在 goroutine 的最后往 channel 里面放东西,然后主协程里面从 channel 里面获取东西,只需要次数一致就可以了。这种方式也是官方推荐的同步方式,sync 通常用于比较底层的同步。为了等待 goroutine 结束,我们可以使用。原创 2024-01-23 08:00:00 · 452 阅读 · 0 评论 -
Go json 能否解码到一个 interface 类型的值
通过代码描述一下这里的具体操作:答案:不行。具体就是,我有一个结构体 实现了接口 ,然后 里面有 属性,然后在反序列化的时候,用指向 ,类型的值来接收。结果就是,结构体里面字段都丢失了。如果我们写成下面这样,就可能错过了发现错误的机会(我一开始就是这么写的):如果打印错误的话,其实编译器已经给出了明确的报错信息:原因在反序列化的时候,反射处理是拿不到那个值的具体类型的。参考链接:https://stackoverflow.com/questions/32428797/unmarshal-to-原创 2024-01-23 08:00:00 · 383 阅读 · 0 评论 -
Golang bytes 包学习
视为 UTF-8 编码的字节,并返回一个副本,其中所有 Unicode 字母均映射到其标题大小写,并优先使用特殊的大小写规则。视为 UTF-8 编码的字节,并返回一个副本,其中所有 Unicode 字母均映射为它们的大写字母,优先考虑特殊的大小写规则。定义的空白字符来拆分该字节切片,但是拆分的结果不会包含空白字符。类似,不过接收一个自定义的回调函数来判断字符是否是满足条件的字符,是则返回 true,这个字符的索引就是。视为 UTF-8 编码的字节,并返回一个副本,将其中无效的 UTF-8 替换为。原创 2024-01-22 08:00:00 · 1076 阅读 · 0 评论 -
Golang modules 使用
Golang 1.11 推出了 modules 机制来进行依赖管理。原创 2024-01-22 08:00:00 · 1057 阅读 · 0 评论 -
golang 反射基本原理及用法
接口是静态类型的:接口类型的变量始终具有相同的类型,即使在运行时存储在接口变量中的值可能会更改类型,该值也始终满足接口的要求。**接口类型的变量存储了一对值:分配给该变量的具体值,以及该值的类型描述。**更确切地说,该值是实现接口的基础具体数据项,而类型描述了该数据项的完整类型。从底层讲,反射只是一种检查存储在接口变量中的值和类型对的机制。在下面的例子中,我们使用结构体的地址创建反射对象,因为稍后将要对其进行修改。里面包含的值依然持有它原来的值,所以这个断言是没有问题的。,而不是传递的接口值。原创 2024-01-21 08:00:00 · 956 阅读 · 0 评论 -
Golang 搭建 WebSocket 应用(八) - 完整代码
本文应该是本系列文章最后一篇了,前面留下的一些坑可能后面会再补充一下,但不在本系列文章中了。原创 2024-01-21 08:00:00 · 587 阅读 · 0 评论 -
Golang 搭建 WebSocket 应用(七) - 性能、可用性
关于性能,其实并不是只有我们这个消息推送系统独有的问题。对于所有的开发者而言,都多多少少会处理过性能相关的问题,比如后端为了减少数据库查询提高并发引入的缓存中间件,如redis;又或者如前端一次性渲染大量数据的时候,如果让用户体验更加流畅等。本文会针对WebSocket应用场景下去思考一些可能出现的性能问题以及可行的解决方案。具体来说,我们的系统中会有下面几个可能的地方会导致产生性能问题:连接数:一个连接会有两个协程,另外每一个Client结构体也会需要一定的缓冲区来缓冲发送给客户端的消息。原创 2024-01-20 08:00:00 · 987 阅读 · 0 评论 -
Golang 搭建 WebSocket 应用(六) - 监控
本人文章可能文字会比较多,但是其中都是个人在此过程中的一些思考,相比直接告诉大家怎么做,有可能知道为什么这么做更重要。消息推送这个功能,技术上其实我们已经实现了,但是我们还得考虑很多非功能性的需求,这些非功能性的需求决定了我们的架构。依赖倒置原则可以指导我们设计出具有扩展性的代码:本文中的日志记录抽象出了一个,需要的时候我们可以自行实现然后替换掉框架提供的实现。错误处理:为了方便后续维护,处理处理我们也是抽象出了一个func类型,实现了关注点的分离,也在一定程度上给后续的扩展提供了可能。原创 2024-01-20 08:00:00 · 1092 阅读 · 0 评论 -
Golang 搭建 WebSocket 应用(五) - 消息推送日志
本人文章可能文字会比较多,但是其中都是个人在此过程中的一些思考,相比直接告诉大家怎么做,有可能知道为什么这么做更重要。消息推送这个功能,技术上其实我们已经实现了,但是我们还得考虑很多非功能性的需求,这些非功能性的需求决定了我们的架构。依赖倒置原则可以指导我们设计出具有扩展性的代码:本文中的日志记录抽象出了一个,需要的时候我们可以自行实现然后替换掉框架提供的实现。错误处理:为了方便后续维护,处理处理我们也是抽象出了一个func类型,实现了关注点的分离,也在一定程度上给后续的扩展提供了可能。原创 2024-01-19 08:00:00 · 1088 阅读 · 0 评论 -
Golang 搭建 WebSocket 应用(四) - jwt 认证
JWT是的缩写,是一种用于在网络中安全传递信息的开放标准。它是一种紧凑且自包含的方式,用于在各方之间传递信息,通常用于身份验证和授权机制。JWT主要由三个部分组成:头部(Header): 包含关于令牌的元数据,例如令牌的类型(typ)和签名算法(alg头部是一个JSON对象,通常会经过Base64编码。载荷(Payload): 包含要传递的信息,通常包括用户身份信息以及其他声明。载荷也是一个JSON对象,同样经过Base64编码。签名(Signature。原创 2024-01-19 08:00:00 · 1710 阅读 · 0 评论 -
Golang 搭建 WebSocket 应用(三) - 实现一个消息推送中心
有了前两篇的铺垫,相信大家已经对 Golang 中WebSocket的使用有一定的了解了,今天我们以一个更加真实的例子来学习如何在 Golang 中使用WebSocket。原创 2024-01-18 08:00:00 · 1844 阅读 · 0 评论 -
Golang 搭建 WebSocket 应用(二) - 基本群聊 demo
上一篇文章中,我们已经了解了的一些基本概念和简单的用法。接下来,我们通过一个再复杂一点的例子来了解它的实际用法。原创 2024-01-18 08:00:00 · 1105 阅读 · 0 评论