Rookiecom

Rookiecom

一个探索者,处于技术上升期

Go 读写锁源码阅读

问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 var lock sync.RWMutex var wg *sync.WaitGroup func Writer(ctx context.Context) { ticker := time.NewTicker(10 * time.Millisecond) defer ticker.Stop() for { select { case <-ticker.C: lock.Lock() time.Sleep(5 * time.Millisecond) lock.Unlock() case <-ctx.Done(): return } } } func Reader() { defer wg.

Go Context底层原理

前言 go 中常常使用 context 来作为协程之间传递消息。使用场景常常有: 传递一个任务的元信息:在微服务中,常常将 traceID 写入在上下文的键值对中,用于追踪一个请求的调用链。 传递取消信号:父协程并发开启子协程执行任务,但是父协程也许会检测到什么信号(时间截止、任务结束),这个时候父协程可以使用 context 的取消功能结束所有子协程。 在使用的过程中,我常常有疑问: 不同函数之间传递的 context 对象是值引用还是指针引用 父子协程同时访问 context 并发安全吗 父协程执行取消函数做了什么?子协程开启的孙协程也会终止吗? 带着问题,我阅读了 context 的源码(go 版本 1.19),了解了 context 的设计。 类型 上下文一共有以下 4 种类型: emptyCtx:最基础的 context,只是表征一个类型 valueCtx:带键值对的context cancelCtx:带取消功能的context timerCtx:带定时取消功能的 context 在这 4 中类型中,最重要的是 valueCtx、cancelCtx,两者可以构建 context 包的几乎所有功能。 context 包定义了一组接口: 1 2 3 4 5 6 type Context interface { Deadline() (deadline time.Time, ok bool) // 用于子协程获取deadline Done() <-chan struct{} // 用于子协程获取管道的取消信号 Err() error // 返回上下文被取消或超时时的错误信息 Value(key any) any // 用于获取键值对 } 只要实现这一组接口就算就能算作 Context 类型。

装饰者模式

问题:星巴克售卖饮品,需要计算饮品的价格。饮品有几种基础饮品:无咖啡因咖啡、超优深焙咖啡、浓咖啡等等,每个基础饮品可以添加调料最后产生最终的饮品。由于星巴克扩张迅速,需要快速退出新品,调料和基础饮品都可以增加和改变,如何设计系统,才能优雅的应对调料和基础饮品的增加。 核心思想:用组合代替继承,来扩张类的功能 设计原则:类应该对扩展开放,对修改关闭 实现:一个最基础的类,这个类会有一个接口 cost,每个基础饮品都需要实现继承这个基础类,实现 cost 接口(基础饮品的价格)。装饰者类继承这个基础类(可以添加一些新的方法比如 printDescription()), 每个装饰者都应该继承这个装饰者类或者实现这个装饰者类的接口(go 中的 interface) 缺陷:由于每个调料都是一个装饰者(类),在实现过程中,会依赖大量的类,声明大量类的实例,不便于管理,工厂模式和生成器模式会解决这个问题 示例代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 class beverage { string description; public: beverage() {} beverage(string s) : description(s) {} virtual string describe() { return description; } virtual double cost() = 0; }; class Espresso : public beverage { public: Espresso() : beverage("浓咖啡") {} double cost() override { return 2.
0%