发布时间:2026/8/29 6:50:11
Go常用的设计模式 Go常用的设计模式常见的设计模式如单例模式、工厂模式、策略模式、观察者模式、代理模式、装饰器模式和适配器模式都可以在 Go 中实现适用于不同的开发需求。这些设计模式不仅能帮助你编写结构清晰、可维护的代码还能让你更好地应对复杂的编程问题。一、单例模式Singleton简介​ Go 的单例模式Singleton Pattern适用于某些需要确保一个类或结构体在整个应用程序中只有一个实例的场景。通常情况下单例模式用于全局共享资源、缓存、日志管理、数据库连接等场景避免了不必要的对象创建和资源浪费。使用场景配置管理日志管理数据连接池缓存管理线程安全的全局状态管理系统资源管理优点线程安全使用sync.Once可以确保在并发环境下单例对象只被创建一次避免竞态条件和数据竞争。延迟初始化懒汉式只有在首次调用时才进行实例化节省内存和启动时间。全局唯一性单例模式可以确保在整个程序生命周期中只有一个实例适合需要共享资源的场景如配置管理、日志记录。节省资源由于实例只创建一次避免频繁创建和销毁带来的性能瓶颈。方便访问单例模式提供一个全局访问点通过调用同一个函数即可获取实例方便在整个程序中使用。缺点全局状态导致代码难以测试单例模式带来的全局状态使得单元测试难以编写尤其是需要模拟或替换单例时。难以扩展单例模式将创建逻辑硬编码唉单例类中如果需要更改创建逻辑往往需要修改核心代码违反开闭原则。隐藏依赖性使用单例时其他模块可能隐式依赖于单例对象在修改单例时容易引发不可预期的问题。不利于并行测试由于单例模式在程序中只有一个实例多个测试用例无法并发运行可能产生数据污染。潜在内存泄露如果单例中持有大量资源且没有及时释放可能导致内存泄漏。实现packagemainimport(fmtsync)typeSingletonstruct{// 可能包含一些属性}varinstance*Singletonvaronce sync.OncefuncGetInstance()*Singleton{once.Do(func(){instanceSingleton{}})returninstance}funcmain(){s1:GetInstance()s2:GetInstance()fmt.Println(s1s2)// true}二、工厂模式Factory简介​ 工厂模式用于创建对象的实例但不暴露具体的创建逻辑它通过接口来解耦对象的创建和使用。使用场景构建复杂对象如果对象创建过程复杂且有多种变体使用工厂可以贱货创建逻辑。接口实例化当代码中涉及多个实现相同接口的结构体时使用工厂可以屏蔽具体实现方便切换。减少重复代码如果对象创建涉及大量重复逻辑工厂方法可以封装这些逻辑。依赖注入DI和解耦使用工厂可以避免代码中直接依赖具体实现类提升代码灵活性。面向接口编程在某昔日场景下需要根据配置或运行时条件来创建不同的实例。优点解耦性高工厂方法将对象创建与对象使用分离调用者无需关心对象的具体创建过程。符合开闭原则增加新产品时只需增加新的工厂方法而无需修改原有代码减少了对现有代码的侵入。增强代码复用性工厂方法可以复用已有的创建逻辑避免代码重复。代码结构清晰通过工厂模式管理对象创建逻辑使代码结构更加清晰和规范。便于扩展和维护由于工厂模式使用接口和多态特性当需要新增类型时不影响原有代码。缺点复杂性增加简单场景下使用工厂模式多此一举反而增加了代码复杂度。不适用于简单对象如果对象创建很简单工厂模式会引入不必要的抽象降低代码可读性。难以追踪工厂方法隐藏了具体实现可能让代码调用链变长增加调试难度。类爆炸问题如果产品种类繁多则每种产品都需要一个对应的工厂类导致类的数量大幅增加。实现简单工厂模式适用对象较少创建、逻辑简单的场景。packagemainimport(fmt)// 通知接口typeNotifierinterface{Notify(messagestring)}// 邮件通知typeEmailNotifierstruct{}func(e*EmailNotifier)Notify(messagestring){fmt.Println(Email Notification:,message)}// 短信通知typeSMSNotifierstruct{}func(s*SMSNotifier)Notify(messagestring){fmt.Println(SMS Notification:,message)}// 工厂函数funcNewNotifier(notifyTypestring)Notifier{switchnotifyType{caseemail:returnEmailNotifier{}casesms:returnSMSNotifier{}default:returnnil}}funcmain(){notifier:NewNotifier(email)ifnotifier!nil{notifier.Notify(Hello via Email!)}notifierNewNotifier(sms)ifnotifier!nil{notifier.Notify(Hello via SMS!)}}三、策略模式Strategy Pattern简介​ 一种行为设计模式旨在将一组算法封装到独立的类中使它们可以互相替换通过使用策略模式算法的变化不会影响使用算法的上下文代码。策略模式在Go语言中尤为常见因为接口和结构体组合的特性使得实现即灵活又高效。使用场景算法族有多个可替换算法的场景例如加密、排序。业务规则变化频繁例如支付策略、折扣策略。避免使用条件语句如大量if-else或switch判断的地方。优点灵活性可以在运行时动态更改策略。代码复用不同算法独立封装避免了条件语句的堆叠。遵循开闭原则添加新策略时无需修改上下文类。缺点复杂性每个策略需要创建一个类或结构体增加代码量。策略暴漏客户端需要知道有哪些策略才能进行选择。实现packagemainimportfmt// 策略接口typeStrategyinterface{Execute(a,bint)int}// 加法策略typeAddStrategystruct{}func(s AddStrategy)Execute(a,bint)int{returnab}// 乘法策略typeMultiplyStrategystruct{}func(s MultiplyStrategy)Execute(a,bint)int{returna*b}// 上下文结构体typeContextstruct{strategy Strategy}// 设置策略func(c*Context)SetStrategy(strategy Strategy){c.strategystrategy}// 执行策略func(c*Context)ExecuteStrategy(a,bint)int{returnc.strategy.Execute(a,b)}funcmain(){context:Context{}// 使用加法策略context.SetStrategy(AddStrategy{})result:context.ExecuteStrategy(5,3)fmt.Println(加法策略结果:,result)// 输出8// 使用乘法策略context.SetStrategy(MultiplyStrategy{})resultcontext.ExecuteStrategy(5,3)fmt.Println(乘法策略结果:,result)// 输出15}四、观察者模式Observer Pattern简介​ 一种行为设计模式允许对象在其状态发生更改时通知其他依赖对象。它定义了一种一对多的依赖关系一个对象主题/被观察者状态变化时所有依赖者观察者都会收到通知并自动更新。使用场景事件驱动系统如GUI事件监听、消息广播系统。订阅-发布系统如新闻发布、股票行情更新。监控系统如服务健康状态监控和报警。优点解耦主题和观察者之间的耦合性低便于独立扩展。灵活性可以在运行时动态添加和删除观察者。实时更新状态变化时自动通知观察者符合实时性需求。缺点通知滞后当观察者数量较多时通知操作可能会有一定延迟。内存泄露风险如果没有正确管理观察者的注销可能会导致内存泄漏。调试难度较大链式调用可能增加排查时问题的复杂性。实现packagemainimportfmt// 观察者接口typeObserverinterface{Update(messagestring)}// 主题接口typeSubjectinterface{Register(observer Observer)Unregister(observer Observer)NotifyAll(messagestring)}// 具体主题typeNewsPublisherstruct{observers[]Observer}// 注册观察者func(n*NewsPublisher)Register(observer Observer){n.observersappend(n.observers,observer)}// 注销观察者func(n*NewsPublisher)Unregister(observer Observer){fori,obs:rangen.observers{ifobsobserver{n.observersappend(n.observers[:i],n.observers[i1:]...)break}}}// 通知所有观察者func(n*NewsPublisher)NotifyAll(messagestring){for_,observer:rangen.observers{observer.Update(message)}}// 具体观察者typeNewsSubscriberstruct{namestring}// 接收更新通知func(n*NewsSubscriber)Update(messagestring){fmt.Printf([%s] 收到新闻更新%s\n,n.name,message)}// 创建新的观察者funcNewSubscriber(namestring)*NewsSubscriber{returnNewsSubscriber{name:name}}funcmain(){// 创建新闻发布者主题 隐式使用// var publisher Subject NewsPublisher{}publisher:NewsPublisher{}// 创建观察者订阅者sub1:NewSubscriber(Alice)sub2:NewSubscriber(Bob)sub3:NewSubscriber(Charlie)// 注册观察者publisher.Register(sub1)publisher.Register(sub2)publisher.Register(sub3)// 发布新闻更新publisher.NotifyAll(Go 1.21 发布了)// 注销一个观察者publisher.Unregister(sub2)// 再次发布新闻publisher.NotifyAll(Go 1.22 即将发布)}五、代理模式Proxy Pattern简介​ 一种结构型设计模式它通过一个代理对象来控制对目标对象的访问。代理对象可以在客户端和真实对象之间进行一些操作比如权限控制、懒加载、日志记录、缓存等特别适合增强现有类的功能而无需修改原有代码。使用场景远程代理使用代理来控制对远程服务的访问。虚拟代理延迟初始化较为复杂的对象。安全代理检查权限只有合法用户才能访问。只能引用代理自动进行医用计数和资源管理。优点职责分离代理对象负责处理非核心业务如日志记录核心业务由真实对象完成。灵活性强可以动态地将额外操作附加到真实对象上。曾强功能在不修改原始类的情况下增加新功能。缺点开销增加由于增加了代理对象性能有一定损耗。代码复杂增加了代码复杂性和维护难度。实现packagemainimport(fmttime)// 抽象接口SubjecttypeBankAccountinterface{Deposit(amountfloat64)Withdraw(amountfloat64)GetBalance()float64}// 实际对象RealSubject银行账户typeRealBankAccountstruct{balancefloat64}func(r*RealBankAccount)Deposit(amountfloat64){r.balanceamount fmt.Printf(存入%.2f 元当前余额%.2f 元\n,amount,r.balance)}func(r*RealBankAccount)Withdraw(amountfloat64){ifamountr.balance{fmt.Println(余额不足取款失败)return}r.balance-amount fmt.Printf(取出%.2f 元当前余额%.2f 元\n,amount,r.balance)}func(r*RealBankAccount)GetBalance()float64{returnr.balance}// 代理对象Proxy日志代理typeLoggingProxystruct{realAccount BankAccount}funcNewLoggingProxy(realAccount BankAccount)*LoggingProxy{returnLoggingProxy{realAccount:realAccount}}func(p*LoggingProxy)Deposit(amountfloat64){fmt.Printf([%s] 正在进行存款操作...\n,time.Now().Format(2006-01-02 15:04:05))p.realAccount.Deposit(amount)}func(p*LoggingProxy)Withdraw(amountfloat64){fmt.Printf([%s] 正在进行取款操作...\n,time.Now().Format(2006-01-02 15:04:05))p.realAccount.Withdraw(amount)}func(p*LoggingProxy)GetBalance()float64{balance:p.realAccount.GetBalance()fmt.Printf([%s] 查询余额%.2f 元\n,time.Now().Format(2006-01-02 15:04:05),balance)returnbalance}// 客户端代码funcmain(){// 创建实际银行账户realAccount:RealBankAccount{}// 使用代理来包装实际账户proxy:NewLoggingProxy(realAccount)// 通过代理进行操作proxy.Deposit(1000)proxy.Withdraw(300)proxy.GetBalance()}六、装饰器模式简介​ 一种结构型设计模式允许在不修改对象结构的情况下动态地为对象添加新功能。使用场景功能增强为对象动态添加功能。替代子类继承通过组合而非继承来扩展功能。职责划分使每个装饰器负责特定功能符合单一职责原则。装饰器模式的核心思想组件接口Component定义一个可以被装饰的对象接口。具体组件Concrete Component实现基础功能。装饰器接口Decorator持有组件接口的引用且具有相同的方法。具体装饰器Concrete Decorator扩展组件的功能。优点灵活性高可以通过多个装饰器动态组合新功能。符合开闭原则可以随时添加新装饰器而不影响原有代码。职责单一每个装饰器只负责一个特定功能。缺点装饰链过长可能导致结构复杂难以维护。性能开销多层嵌套会带来性能损耗。实现packagemainimport(fmt)// Component 接口咖啡饮品typeBeverageinterface{GetDescription()stringCost()float64}// 具体组件基础咖啡typeEspressostruct{}func(e*Espresso)GetDescription()string{returnEspresso}func(e*Espresso)Cost()float64{return15.0}// 装饰器基类实现 Beverage 接口typeCondimentDecoratorstruct{beverage Beverage}func(c*CondimentDecorator)GetDescription()string{returnc.beverage.GetDescription()}func(c*CondimentDecorator)Cost()float64{returnc.beverage.Cost()}// 具体装饰器牛奶typeMilkstruct{CondimentDecorator}funcNewMilk(beverage Beverage)*Milk{returnMilk{CondimentDecorator{beverage}}}func(m*Milk)GetDescription()string{returnm.beverage.GetDescription(), Milk}func(m*Milk)Cost()float64{returnm.beverage.Cost()3.5}// 具体装饰器糖typeSugarstruct{CondimentDecorator}funcNewSugar(beverage Beverage)*Sugar{returnSugar{CondimentDecorator{beverage}}}func(s*Sugar)GetDescription()string{returns.beverage.GetDescription(), Sugar}func(s*Sugar)Cost()float64{returns.beverage.Cost()1.0}// 客户端代码funcmain(){// 创建基础咖啡varbeverage BeverageEspresso{}fmt.Printf(饮品%s价格%.2f 元\n,beverage.GetDescription(),beverage.Cost())// 加牛奶beverageNewMilk(beverage)fmt.Printf(饮品%s价格%.2f 元\n,beverage.GetDescription(),beverage.Cost())// 再加糖beverageNewSugar(beverage)fmt.Printf(饮品%s价格%.2f 元\n,beverage.GetDescription(),beverage.Cost())}装饰器模式和代理模式对比特性装饰器模式代理模式主要目的动态扩展功能控制对对象的访问结构特点组合多个装饰器形成链代理对象持有实际对象的引用典型应用场景日志、性能监控、权限校验、增强对象功能远程代理、虚拟代理、安全代理、缓存代理七、适配器模式Adapter Pattern简介​ 一种结构型设计模式它通过两个不兼容的接口提供一个适配器使得它们能够一起工作。适配器模式可以将一个接口转换为客户端期望的另一个接口目的时让不兼容的接口能过够合作。使用场景多重接口适配统一接口标准在一个系统中你可能需要使用多个不兼容的接口而这些接口都执行类似的操作。适配器模式可以帮助你统一这些接口使得系统中其他部分可以通过相同的接口与它们交互。兼容性问题与现有系统兼容如果你正在集成一个第三方库或者使用一个遗留系统而该系统的接口与现有系统不兼容适配器模式可以帮助你转换这些不兼容的接口使得它们能够顺利协作。第三方库接口的适配外部API整合当使用第三方库时这些库通常提供不同的接口而你希望用一个统一的接口访问这些库。适配器模式可以将第三方库的接口适配为你项目中需要的标准接口。接口升级或变化当你需要对现有接口进行修改但又不希望影响到客户端的代码时适配器模式可以帮助你维护原接口的兼容性同时在背后对接口进行改造或升级。不同硬件或设备的适配当你在开发跨平台应用或者硬件交互时可能需要适配不同硬件或设备的接口。适配器模式可以帮助将不同硬件提供的接口适配到你应用需要的标准接口上。系统迁移或重构在系统重构的过程中可能会涉及到接口的更改而你又希望让现有代码与新代码兼容。适配器模式能够在过渡期间无缝衔接新旧系统的接口。替代继承的场景类适配如果一个类不适用于继承的方式或者你不想改变原有类的结构可以使用适配器模式代替继承来扩展功能。API或数据协议的适配不同的系统或组件之间可能使用不同的数据格式或协议适配器模式能够在这些不同的格式之间提供一个桥梁。适配器模式的核心思想目标接口Target客户端期望使用的接口。源接口Adaptee需要适配的现有接口它的方法不能直接与客户端使用的接口兼容。适配器Adapter将源接口转换为目标接口使得客户端可以通过目标接口使用源接口的功能。优点兼容不兼容的接口使得本来不兼容的接口通过适配器能够协同工作。符合开闭原则通过适配器可以在不修改原有类的情况下改变接口的使用方式。解耦客户端不需要知道适配器的实现只需要依赖目标接口。缺点增加代码复杂性适配器模式会引入额外的类和对象可能增加代码的复杂性。性能开销在适配器模式中通常有额外的间接调用可能导致轻微的性能损失。实现packagemainimportfmt// 目标接口Target要求的电源接口typePowerOutletinterface{SupplyPower()string}// 源接口Adaptee我们现有的电源接口typeTwoPinSocketstruct{}func(s*TwoPinSocket)ProvidePower()string{return提供 220V 电流}// 适配器Adapter将现有电源接口转换为目标接口typeAdapterstruct{socket*TwoPinSocket}// 适配器的方法使其实现目标接口func(a*Adapter)SupplyPower()string{returna.socket.ProvidePower()}// 客户端代码funcmain(){// 使用现有的 2 针电源插座不符合目标接口twoPinSocket:TwoPinSocket{}// 通过适配器将其转换为目标接口adapter:Adapter{socket:twoPinSocket}// 客户端通过目标接口使用适配后的电源fmt.Println(设备电源,adapter.SupplyPower())}适配器模式与代理模式的对比特性适配器模式代理模式主要目的使接口兼容并进行转换适配不同接口的类控制对目标对象的访问通常是延迟或虚拟化操作。结构特点客户端和目标接口之间通过适配器进行转换代理对象持有实际对象的引用进行控制访问典型应用场景使得不兼容的类能够协作转换接口控制对实际对象的访问如延迟加载、远程调用等

相关新闻

2026/8/28 19:10:54

牙齿护理笔记

1. 牙齿笔记 您好,我是一名博士生; 3月5日,对25牙做了根管治疗; 请您担任我的健康顾问,我今天感到有些不适,我在手机上观看在线课程时,我感到有点头昏、太阳穴有些发紧,口腔牙床感到…

2026/8/27 12:33:10

亚马逊玩具卖家必看:2026最新TIC认证全攻略,从懵圈到通关一篇搞定

> 告别自己上传报告的时代,手把手教你如何通过亚马逊官方认可的TIC直接验证。 如果你是亚马逊卖家,正在为玩具类目的合规审查焦头烂额,那么你来对地方了。2025年起,亚马逊对玩具类目实施了最严厉的合规新政——TIC(Testing, Inspection, and Certification,即测试、检…

2026/8/29 6:47:00

网易HCI算法工程师校招笔试考点全拆解:人机交互+算法双线攻略

2018年那个秋招季,我投了网易的人机交互算法工程师。说实话,刚看到这个岗位名称的时候心里有点犯嘀咕——人机交互听着像产品经理干的事,算法工程师又像是纯写模型的,这俩揉在一起到底考什么?直到我打开在线笔试系统&a…

2026/8/29 6:47:00

量化交易中均线维度的系统化构建:从参数设定到算法实现

1. 从“线”到“维”:重新理解均线在算法交易中的定位在交易的世界里,移动平均线(MA)可能是每个入门者最先接触到的工具。它简单、直观,一根线似乎就能勾勒出价格的趋势。但当我们谈论“四维全息算法”中的“均线维度”…

2026/8/29 6:47:00

一维河流稳态水质模型:从对流扩散方程到MATLAB有限差分求解

1. 从实际问题到数学模型:为什么我们需要稳态水质模型在长江沿岸的某个城市,环保部门面临一个棘手的难题:上游的工业区持续排放含有特定污染物的废水,他们需要预测这些污染物在下游几十公里范围内的浓度分布,以便评估对…

2026/8/29 6:47:00

非线性规划在数学建模中的核心应用与Matlab实战指南

1. 从“线性”到“非线性”:一个更真实的世界模型如果你接触过数学建模,大概率是从线性规划开始的。那个经典的“资源分配”问题:用有限的原料生产几种产品,每种产品利润固定,目标是最大化总利润。公式写出来&#xff…

2026/8/29 6:42:00

零代码数字孪生平台有哪些?没有3D基础的人适合用什么

不少朋友在问:"有哪些数字孪生开发平台是零代码的,适合没有3D基础的人能掌握吗?"答案是肯定的。零代码数字孪生平台通过拖拽式操作和可视化编辑器,让没有 3D 开发背景的业务人员也能搭建三维场景。本文盘点主流零代码数…

2026/8/28 16:16:17

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/28 16:16:21

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/28 16:16:22

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/29 0:01:10

etc目录下的profile.d文件目录设置环境变量和全局脚本shell

一、设置环境变量etc目录下的profile.d文件目录 /etc/profile.d1、编写 vi test.sh文件内容# jdk变量 export ZHK_HOME/root export PATH$PATH:$ZHK_HOME/test # 可以取出来ZHK_HOME变量给ZZZ_HOME赋值 export ZZZ_HOME${ZHK_HOME}/test2、刷新 执行source /etc/profile 命令使…

2026/8/29 0:01:10

【JavaScript】内存管理-垃圾回收机制-内存泄露

内存管理 C 语言这样的底层语言一般都有底层的内存管理接口,比如 malloc()和free()。 而 JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。释放的过程称为垃圾回收。 整…

2026/8/29 0:01:10

Labgrid-MCP:为嵌入式硬件实验室接入AI Agent操控能力

Labgrid-MCP 的目标是把 MCP(Model Context Protocol)能力延伸到真实嵌入式硬件实验室:AI Agent 通过一个标准化的 MCP Server,就能查看目标板状态、控制上电断电、复位开发板、读取串口日志,甚至执行镜像刷写。对于经…

2026/8/28 16:16:48

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/28 16:16:50

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/28 11:06:45

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…