想要写好Go并发不得不掌握的数据结构(2)
想要写好Go并发不得不掌握的数据结构(2)Channel要想了解 Channel 这种 Go 编程语言中的特有的数据结构,我们要追溯到 CSP 模型,学习一下它的历史,以及它对 Go 创始人设计 Channel 类型的影响。CSP 是 Communicating Sequential Process 的简称,中文直译为通信顺序进程,或者叫做交换信息的循序进程,是用来描述并发系统中进行交互的一种模式。CSP 最早出现于计算机科学家 Tony Hoare 在 1978 年发表的论文中(你可能不熟悉 Tony Hoare 这个名字,但是你一定很熟悉排序算法中的 Quicksort 算法,他就是 Quicksort 算法的作者,图灵奖的获得者)。最初,论文中提出的 CSP 版本在本质上不是一种进程演算,而是一种并发编程语言,但之后又经过了一系列的改进,最终发展并精炼出 CSP 的理论。CSP 允许使用进程组件来描述系统,它们独立运行,并且只通过消息传递的方式通信。
Channel 的应用场景Don’t communicate by sharing memory, share memory by ...
想要写好Go并发不得不掌握的数据结构
想要写好Go并发不得不掌握的数据结构Map哈希表(Hash Table)这个数据结构,我们已经非常熟悉了。它实现的就是 key-value 之间的映射关系,主要提供的方法包括 Add、Lookup、Delete 等。因为这种数据结构是一个基础的数据结构,每个 key 都会有一个唯一的索引值,通过索引可以很快地找到对应的值,所以使用哈希表进行数据的插入和读取都是很快的。Go 语言本身就内建了这样一个数据结构,也就是 map 数据类型。
map 的基本使用方法
1map[K]V
其中,key 类型的 K 必须是可比较的(comparable),也就是可以通过 == 和 != 操作符进行比较;value 的值和类型无所谓,可以是任意的类型,或者为 nil。
在 Go 语言中,bool、整数、浮点数、复数、字符串、指针、Channel、接口都是可比较的,包含可比较元素的 struct 和数组,这俩也是可比较的,而 slice、map、函数值都是不可比较的。
那么,上面这些可比较的数据类型都可以作为 map 的 key 吗?显然不是。通常情况下,我们会选择内建的基本类型,比如整数、字符串做 k ...
设计模式的一些使用原则
设计模式的一些使用原则
之前把23种设计模式结合golang代码总结了一下,但这23种设计模式相当于武功招式,只掌握了武功招式没有内功心法是没办法发挥其作用,你只会盲目的去套用招式这往往会得到相反的效果,我们经常看到过度设计导致代码不但复杂而且性能低下。这一篇文章就总结一下为什么要使用23种设计模式。
用好设计模式首先要了解面向对象:
面向对象设计封装(Encapsulation)封装也叫作信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式(或者叫函数)来访问内部信息或者数据。
封装也叫作信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式来访问内部信息或者数据。它需要编程语言提供权限访问控制语法来支持,例如 Java 中的 private、protected、public 关键字。封装特性存在的意义,一方面是保护数据不被随意修改,提高代码的可维护性;另一方面是仅暴露有限的必要接口,提高类的易用性。
抽象(Abstraction)抽象是从具体事物中提取共性,形成更高层次的概念。
计算机科学中的抽象是通过隐藏细节,简化复杂系统的 ...
结合Golang聊聊23种设计模式---行为型(3)
结合Golang聊聊23种设计模式—行为型(3)责任链模式责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
责任链模式的英文翻译是 Chain Of Responsibility Design Pattern。
在 GoF 的《设计模式》中,它是这么定义的:Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
翻译成中文就是:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
这么说比较抽象,我用更加容易理解的话来进一步解读一下。在 ...
结合Golang聊聊23种设计模式---行为型(2)
结合Golang聊聊23种设计模式—行为型(2)策略模式策略模式,英文全称是 Strategy Design Pattern。在 GoF 的《设计模式》一书中,它是这样定义的:
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
翻译成中文就是:定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。
我们知道,工厂模式是解耦对象的创建和使用,观察者模式是解耦观察者和被观察者。策略模式跟两者类似,也能起到解耦的作用,不过,它解耦的是策略的定义、创建、使用这三部分。
为什么要使用策略模式策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
我们可以利用策略模式来移除 if-else ...
结合Golang聊聊23种设计模式---行为型(1)
结合Golang聊聊23种设计模式—行为型(1)
我们常把 23 种经典的设计模式分为三类:创建型、结构型、行为型。前面我们已经学习了创建型和结构型,从今天起,我们开始学习行为型设计模式。我们知道,创建型设计模式主要解决“对象的创建”问题,结构型设计模式主要解决“类或对象的组合或组装”问题,那行为型设计模式主要解决的就是“类或对象之间的交互”问题。
行为型设计模式比较多,有 11 个,几乎占了 23 种经典设计模式的一半。它们分别是:观察者模式、模板模式、策略模式、职责链模式、状态模式、迭代器模式、访问者模式、备忘录模式、命令模式、解释器模式、中介模式。
观察者模式观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)。在 GoF 的《设计模式》一书中,它的定义是这样的:Define a one-to-many dependency between objects so that when one object changes state, all its dependents are ...
结合Golang聊聊23种设计模式---结构型(2)
结合Golang聊聊23种设计模式—结构型(2)适配器模式适配器模式的英文翻译是 Adapter Design Pattern。顾名思义,这个模式就是用来做适配的
为什么要使用适配器模式适配器模式可以将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。对于这个模式,有一个经常被拿来解释它的例子,就是 USB 转接头充当适配器,把两种不兼容的接口,通过转接变得可以一起工作。
代码示例这里有一段客户端代码, 用于接收一个对象 (Lightning 接口) 的部分功能, 不过我们还有另一个名为 adaptee 的对象 (Windows 笔记本), 可通过不同的接口 (USB 接口) 实现相同的功能
这就是适配器模式发挥作用的场景。 我们可以创建这样一个名为 adapter 的结构体:
遵循符合客户端期望的相同接口 (Lightning 接口)。
可以适合被适配对象的方式对来自客户端的请求进行 “翻译”。 适配器能够接受来自 Lightning 连接器的信息, 并将其转换成 USB 格式的信号, 同时将信号传递给 Windows 笔记本的 USB 接口。
...
结合Golang聊聊23种设计模式---结构型(1)
结合Golang聊聊23种设计模式—结构型(1)结构型模式主要总结了一些类或对象组合在一起的经典结构,这些经典的结构可以解决特定应用场景的问题。结构型模式包括:代理模式、桥接模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式。
代理模式代理模式(Proxy Design Pattern)它在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。
为什么要使用代理模式第一,防止框架如监控、统计、鉴权、限流、事务、幂等、日志,缓存等代码侵入到业务代码中,跟业务代码高度耦合。如果未来需要替换这个框架,那替换的成本会比较大。
第二,框架代码跟业务代码无关,本就不应该放到一个类中。业务类最好职责更加单一,只聚焦业务处理。
代理类负责在业务代码执行前后附加其他逻辑代码,并通过委托的方式调用原始类来执行业务代码。具体的代码实现如下所示:
Nginx 这样的 Web 服务器可充当应用程序服务器的代理:
提供了对应用程序服务器的受控访问权限。
可限制速度。
可缓存请求。
server.go: 主体12345package maintype server interfac ...
结合Golang聊聊23种设计模式---创建型
结合Golang聊聊23种设计模式—创建型
将不要过度设计也不要随意堆砌烂代码写在前面设计模式要干的事情就是解耦,也就是利用更好的代码结构将一大坨代码拆分成职责更单一的小类,让其满足高内聚低耦合等特性。创建型模式是将创建和使用代码解耦,结构型模式是将不同的功能代码解耦,行为型模式是将不同的行为代码解耦。而解耦的主要目的是应对代码的复杂性。设计模式就是为了解决复杂代码问题而产生的。因此,对于复杂代码,比如项目代码量多、开发周期长、参与开发的人员多,我们前期要多花点时间在设计上,越是复杂代码,花在设计上的时间就要越多。 不仅如此,每次提交的代码,都要保证代码质量,都要经过足够的思考和精心的设计,这样才能避免烂代码效应(每次提交的代码质量都不是太好,最终积累起来整个项目的质量就变得很差)。相反,如果你参与的只是一个简单的项目,代码量不多,开发人员也不多,那简单的问题用简单的解决方案就好,不要引入过于复杂的设计模式,将简单问题复杂化。
单例模式为什么要使用单例?单例设计模式(Singleton Design Pattern)理解起来非常简单。一个类只允许创建一个对象(或者实例),那这个类就是 ...
Mysql--如何实现高可用
Mysql 如何实现高可用主备一致客户端的读写都直接访问节点 A,而节点 B 是 A 的备库,只是将 A 的更新都同步过来,到本地执行。这样可以保持节点 B 和 A 的数据是相同的。
接下来,我们再看看节点 A 到 B 这条线的内部流程是什么样的。图 2 中画出的就是一个 update 语句在节点 A 执行,然后同步到节点 B 的完整流程图。
备库 B 跟主库 A 之间维持了一个长连接。主库 A 内部有一个线程,专门用于服务备库 B 的这个长连接。一个事务日志同步的完整过程是这样的:
在备库 B 上通过 change master 命令,设置主库 A 的 IP、端口、用户名、密码,以及要从哪个位置开始请求 binlog,这个位置包含文件名和日志偏移量。
在备库 B 上执行 start slave 命令,这时候备库会启动两个线程,就是图中的 io_thread 和 sql_thread。其中 io_thread 负责与主库建立连接。
主库 A 校验完用户名、密码后,开始按照备库 B 传过来的位置,从本地读取 binlog,发给 B。
备库 B 拿到 binlog 后,写到本地文件,称 ...





