详解 Go 空结构体的 3 种使用场景

大家好,我是煎鱼。 在大家初识 Go 语言时,总会拿其他语言的基本特性来类比 Go 语言,说白了就是老知识和新知识产生关联,实现更高的学习效率。 最常见的类比,就是 “Go 语言如何实现面向对象?”,进一步展开就是 Go 语言如何实现面向对象特性中的继承。 这不仅在学习中才用到类比,在业内的 Go 面试中也有非常多的面试官喜欢问: 来自读者微信群 在今天这篇文章中,煎鱼带大家具体展开了解这块的知识。一起愉快地开始吸鱼之路。 什么是面向对象 在了解 Go 语言是不是面向对象(简称:OOP) 之前,我们必须先知道 OOP 是啥,得先给他 “下定义”。 根据 Wikipedia 的定义,我们梳理出 OOP 的几个基本认知: 面向对象编程(OOP)是一种基于 “对象” 概念的编程范式,它可以包含数据和代码:数据以字段的形式存在(通常称为属性或属性),代码以程序的形式存在(通常称为方法)。

Go 凭什么不支持三元运算符?

大家好,我是煎鱼。 这是一个很多其他语言工程师转 Go 语言的时间节点,这就难免不论一番比较。其中一个经典的运算上的就是 “三元运算符”: 为什么 Go 语言不支持三元运算符,Go 不支持三元运算符就是设计的不好,是历史在开倒车吗? 今天就由煎鱼来和大家一起摸索为什么。 三元运算符是什么 三元运算符,在典型的数学意义上,或者从解析器的角度来看,是一个需要三个参数的运算符。而我们日常中,最常见的是二元运算符: x + y x / y x * y 还有一元运算符: -a ~b !c 以及今天的男主角 “三元运算符”。在 C/C++ 等多种语言中,我们可以根据条件声明和初始化变量的习惯来选择性使用三元条件运算符: int index = val > 0 ?

Go 并发读写 sync.map 的强大之处

大家好,我是煎鱼。 在之前的 《为什么 Go map 和 slice 是非线程安全的?》 文章中,我们讨论了 Go 语言的 map 和 slice 非线程安全的问题,基于此引申出了 map 的两种目前在业界使用的最多的并发支持的模式。 分别是: 原生 map + 互斥锁或读写锁 mutex。 标准库 sync.Map(Go1.9及以后)。 有了选择,总是有选择困难症的,这两种到底怎么选,谁的性能更加的好?我有一个朋友说 标准库 sync.

《漫谈 MQ》要消息队列(MQ)有什么用?

大家好,我是煎鱼。想是问题,做是答案。 最近我有一个朋友公司踩了不少消息队列(MQ)的坑,让人无奈不已。因此计划写 MQ 系列的技术文章,来科普更多这块的知识。 目前 MQ 也是互联网应用中非常常用的基础组件了,面试特爱问。基本有一定规模的系统都能看见他的踪影。 无论是 RocketMQ、Kafka、RabbitMQ 等,都围绕着根本的设计出发产生不同的高级功能,甚至可能是雷同的设计有 N 个名字。 什么是 MQ MQ 一般代指消息队列(Message Queue)。它是一个抽象层,允许多个进程(可能在不同的机器上)通过各种模式(例如:点对点,发布订阅等)进行通信。 也可以根据不同的实现,它可以被配置为保证可靠性、错误报告、安全、发现、性能等。 为什么需要 MQ 在当下 MQ 的必要场景,比较经典的说辞就是 “异步、削峰、解耦”。是各类秒杀系统的设计核心,甚至会作为不少云厂商的卖点,每家都有自己的生态圈。 核心分为三个要点: 解耦。 削峰。 异步。 解耦 在业务系统设计中,我们常常会与一个平台系统 A,他汇聚了许许多多的系统的对接。例如,系统 A 作为平台拥有大量用户操作,自然就有非常多的用户行为。

《漫谈 MQ》设计 MQ 的 3 个难点

大家好,我是煎鱼。 前段时间我们分享了漫谈 MQ 的第一期《要消息队列(MQ)有什么用?》,感觉打开了一个新的世界。 但很快就有小伙伴意识到了不妙,既然 MQ 承接了多个系统,那岂不是该有的问题,他都有,又或是更甚。如下: 今天我们就进一步讲讲,设计 MQ 时很有可能会遇到的几个大难点,在业内又配套用了什么解决方案去处理。 几个难点 从结论上来看,设计 MQ 这一个存在。会至少引发三大难点。堪称互联网经典的,也是面试官们最爱问的: 高可用:代表系统的可用性程度,高可用性通常通过提高系统的容错能力来实现,从而减少系统宕机时间。 高并发:代表通过设计保证系统能够同时并行处理很多请求,在同一个时间点,有很多用户同时访问同一系统、API、URL。 高可靠:代表能够满足预计条件的一个系统或组件(例如:备份、故障处理、数据存储以及访问),比较经典的是 4 个9 等标准。 高可用 像前面评论区留言的兄弟截图表述的一样。 虽然请求不直接找系统 A、B、C、D 了。但是请求都实打实的通过异步的方式打到了 MQ 上,就可以不断往 MQ 塞,变成了多个系统都在请求 MQ,可以认为压力比单系统同步调用大了不止一倍。

回答我,停止 Goroutine 有几种方法?

大家好,我是煎鱼。 协程(goroutine)作为 Go 语言的扛把子,经常在各种 Go 工程项目中频繁露面,甚至有人会为了用 goroutine 而强行用他。 在 Go 工程师的面试中,也绕不开他,会有人问 ”如何停止一个 goroutine?”,一下子就把话题范围扩大了,这是一个涉及多个知识点的话题,能进一步深入问。 为此,今天煎鱼就带大家了解一下停止 goroutine 的方法! goroutine 案例 在日常的工作中,我们常会有这样的 Go 代码,go 关键字一把搜起一个 goroutine: func main() { ch := make(chan string, 6) go func() { for { ch <- "脑子进煎鱼了" } }() } 初入 goroutine 大门的开发者可能就完事了,但跑一段时间后,他就可能会遇到一些问题,苦苦排查…

多 Goroutine 如何优雅处理错误?

大家好,我是煎鱼。 在 Go 语言中,goroutine 的使用是非常频繁的,因此在日常编码的时候我们会遇到一个问题,那就是 goroutine 里面的错误处理,怎么做比较好? 这是来自我读者群的问题。作为一个宠粉煎鱼,我默默记下了这个技术话题。今天煎鱼就大家来看看多 goroutine 的错误处理机制也有哪些! 一般来讲,我们的业务代码会是: func main() { var wg sync.WaitGroup wg.Add(2) go func() { log.Println("脑子进煎鱼了") wg.Done() }() go func() { log.Println("煎鱼想报错...") wg.Done() }() time.

小技巧分享:在 Go 如何实现枚举?

大家好,我是煎鱼。 在日常的业务工程开发中,我们常常会有使用枚举值的诉求,枚举控的好,测试值边界一遍过… 有的小伙伴会说,在 Go 语言不是有 iota 类型做枚举吗,那煎鱼你这篇文章还讲什么? 讲道理,Go 语言并没有 enum 关键字,有用过 Protobuf 等的小伙伴知道,Go 语言只是 ”有限的枚举“ 支持,我们也会用常量来定义,枚举值也需要有字面意思的映射。 示例 在一些业务场景下,是没法达到我们的诉求的。示例如下: type FishType int const ( A FishType = iota B C D ) func main() { fmt.

提高 Go 程序健壮性,Fuzzing 要来了!

大家好,我是煎鱼。 就在前几天,Go1.17 beta1 正式发布: 兴冲冲本想着看一下当初在 Go1.17 的计划中,预计会支持的新特性:模糊测试(Fuzzing)。不过没想到…计划赶不上变化,官方正式宣告 Fuzzing 不会出现在 Go1.17 的新功能中。 煎鱼在悲伤之际,发现 Go 在 dev.fuzz 分支上提供了该功能的 Beta 测试,因此今天带大家一起来深入该特性。 什么是 Fuzzing Fuzzing 是一种自动测试技术,包括向计算机程序提供随机数据作为输入。然后监测程序是否出现恐慌、断言失败、无限循环等。 Fuzzing 不是使用一个小的、预先定义好的手动创建的输入集(如单元测试),而是用新的案例不断地测试代码,以努力 ”锻炼“ 有关软件的所有方面。 这听起来很 ”难“。但在过去的几年里,Fuzzing 的技术水平有了很大的提高。Fuzzing 不再是需要专业知识才能成功使用的东西,现代模糊测试策略能更快、更有效地找到有用的输入。

为什么 Go map 和 slice 是非线程安全的?

大家好,我是煎鱼。 初入 Go 语言的大门,有不少的小伙伴会快速的 3 天精通 Go,5 天上手项目,14 天上线业务迭代,21 天排查、定位问题,顺带捎个反省报告。 其中最常见的初级错误,Go 面试较最爱问的问题之一: (来自读者提问) 为什么在 Go 语言里,map 和 slice 不支持并发读写,也就是是非线程安全的,为什么不支持? 见招拆招后,紧接着就会开始讨论如何让他们俩 ”冤家“ 支持并发读写? 今天我们这篇文章就来理一理,了解其前因后果,一起吸鱼学懂 Go 语言。 非线程安全的例子 slice 我们使用多个 goroutine 对类型为 slice 的变量进行操作,看看结果会变的怎么样。