for-loop 与 json.Unmarshal 性能分析概要

在项目中,常常会遇到循环交换赋值的数据处理场景,尤其是 RPC,数据交互格式要转为 Protobuf,赋值是无法避免的。一般会有如下几种做法: for for range json.Marshal/Unmarshal 这时候又面临 “选择困难症”,用哪个好?又想代码量少,又担心性能有没有影响啊… 为了弄清楚这个疑惑,接下来将分别编写三种使用……

阅读全文

来,控制一下 goroutine 的并发数量

问题 1 2 3 4 5 6 7 8 9 10 func main() { userCount := math.MaxInt64 for i := 0; i < userCount; i++ { go func(i int) { // 做一些各种各样的业务逻辑处理 fmt.Printf("go func: %d\n", i) time.Sleep(time.Second) }(i) } } 在这里,假设 userCount 是一个外部传入的参数(不可预测,有可能值非常大),有人会全部丢进去循环。想着全部都并发 goroutine 去同时做某一件事。觉得这样子会效率会更高,对不对! 那么,你觉得这里有没……

阅读全文

Go Slice 最大容量大小是怎么来的

前言 在《深入理解 Go Slice》中,我们提到了 “根据其类型大小去获取能够申请的最大容量大小” 的处理逻辑。今天我们将更深入地去探究一下,底层到底做了什么东西,涉及什么知识点? Go Slice 对应代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 func makeslice(et *_type, len, cap int) slice { maxElements := maxSliceCap(et.size) if len < 0 || uintptr(len) > maxElements { ... } if cap < len || uintptr(cap) > maxElements { ... }……

阅读全文

在 Go 中恰到好处的内存对齐

问题 1 2 3 4 5 6 7 type Part1 struct { a bool b int32 c int8 d int64 e byte } 在开始之前,希望你计算一下 Part1 共占用的大小是多少呢? 1 2 3 4 5 6 7 8 func main() { fmt.Printf("bool size: %d\n", unsafe.Sizeof(bool(true))) fmt.Printf("int32 size: %d\n", unsafe.Sizeof(int32(0))) fmt.Printf("int8 size: %d\n", unsafe.Sizeof(int8(0))) fmt.Printf("int64 size: %d\n", unsafe.Sizeof(int64(0))) fmt.Printf("byte size: %d\n", unsafe.Sizeof(byte(0))) fmt.Printf("string size: %d\n", unsafe.Sizeof("zshipu")) } 输出结果: bool size: 1 int32 size: 4 int8 size: 1 int64 size: 8 byte size: 1 string size: 16 这么一算,Part1 这一个结构体的占用内存大小为 1+4+1+8+1 = 15 个字节。相……

阅读全文

有点不安全却又一亮的 Go unsafe.Pointer

在上一篇文章《深入理解 Go Slice》中,大家会发现其底层数据结构使用了 unsafe.Pointer。因此想着再介绍一下其关联知识 前言 在大家学习 Go 的时候,肯定都学过 “Go 的指针是不支持指针运算和转换” 这个知识点。为什么呢? 首先,Go 是一门静态语言,所有的变量都必须为标量类型。不同的……

阅读全文

深入理解 Go Slice

是什么 在 Go 中,Slice(切片)是抽象在 Array(数组)之上的特殊类型。为了更好地了解 Slice,第一步需要先对 Array 进行理解。深刻了解 Slice 与 Array 之间的区别后,就能更好的对其底层一番摸索 😄 用法 Array 1 2 3 4 5 6 7 8 9 10 func main() { nums := [3]int{} nums[0] = 1 n := nums[0] n = 2 fmt.Printf("nums: %v\n", nums) fmt.Printf("n: %d\n", n) } 我们可得知在 Go 中,数组类型需……

阅读全文

fmt 标准库 --- Print* 是怎么样输出的?

前言 package main import ( "fmt" ) func main() { fmt.Println("Hello World!") } 标准开场见多了,那内部标准库又是怎么输出这段英文的呢?今天一起来围观下源码吧 🤭 原型 func Print(a ...interface{}) (n int, err error) { return Fprint(os.Stdout, a...) } func Println(a ...interface{}) (n int, err error) { return Fprintln(os.Stdout, a...) } func Printf(format string, a ...interface{}) (n int, err error) { return Fprintf(os.Stdout, format, a...) } Print:使用默认格式说明符打印格式并写入标准输出。当两者都不是字符串时,在操作数之间添加……

阅读全文

使用 Gomock 进行单元测试

在实际项目中,需要进行单元测试的时候。却往往发现有一大堆依赖项。这时候就是 Gomock 大显身手的时候了 Gomock 是 Go 语言的一个 mock 框架,官方的那种 🤪 安装 $ go get -u github.com/golang/mock/gomock $ go install github.com/golang/mock/mockgen 第一步:我们将安装 gomock 第三方库和 mock 代码的生成工具 mockgen。而后者可以大大的节省我们的工作量。只需要了解其使用方式就可以 第二步:……

阅读全文

「连载十」分布式链路追踪 gRPC + Opentracing + Zipkin

在实际应用中,你做了那么多 Server 端,写了 N 个 RPC 方法。想看看方法的指标,却无处下手? 本文将通过 gRPC + Opentracing + Zipkin 搭建一个分布式链路追踪系统来实现查看整个系统的链路、性能等指标。 Opentracing 是什么 OpenTracing 通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现 不过 OpenTracing 并不是标准。因为……

阅读全文

「连载九」gRPC Deadlines

前言 在前面的章节中,已经介绍了 gRPC 的基本用法。那你想想,让它这么裸跑真的没问题吗? 那么,肯定是有问题了。今天将介绍 gRPC Deadlines 的用法,这一个必备技巧。内容也比较简单 Deadlines Deadlines 意指截止时间,在 gRPC 中强调 TL;DR(Too long, Don’t read)并建议始终设定截止日期,为什么呢? 为什么要设置 当未设置 Deadlines 时,将采用……

阅读全文