Go常用的设计模式
Go常用的设计模式
常见的设计模式,如 单例模式、工厂模式、策略模式、观察者模式、代理模式、装饰器模式 和 适配器模式 都可以在 Go 中实现,适用于不同的开发需求。
这些设计模式不仅能帮助你编写结构清晰、可维护的代码,还能让你更好地应对复杂的编程问题。
一、单例模式(Singleton)
简介:
Go 的单例模式(Singleton Pattern)适用于某些需要确保一个类(或结构体)在整个应用程序中只有一个实例的场景。通常情况下,单例模式用于全局共享资源、缓存、日志管理、数据库连接等场景,避免了不必要的对象创建和资源浪费。
使用场景:
- 配置管理
- 日志管理
- 数据连接池
- 缓存管理
- 线程安全的全局状态管理
- 系统资源管理
优点:
- 线程安全:使用
sync.Once
可以确保在并发环境下,单例对象只被创建一次,避免竞态条件和数据竞争。 - 延迟初始化(懒汉式):只有在首次调用时才进行实例化,节省内存和启动时间。
- 全局唯一性:单例模式可以确保在整个程序生命周期中只有一个实例,适合需要共享资源的场景(如配置管理、日志记录)。
- 节省资源:由于实例只创建一次,避免频繁创建和销毁带来的性能瓶颈。
- 方便访问:单例模式提供一个全局访问点,通过调用同一个函数即可获取实例,方便在整个程序中使用。
缺点:
- 全局状态导致代码难以测试:单例模式带来的全局状态使得单元测试难以编写,尤其是需要模拟或替换单例时。
- 难以扩展:单例模式将创建逻辑硬编码唉单例类中,如果需要更改创建逻辑,往往需要修改核心代码,违反开闭原则。
- 隐藏依赖性:使用单例时,其他模块可能隐式依赖于单例对象,在修改单例时容易引发不可预期的问题。
- 不利于并行测试:由于单例模式在程序中只有一个实例,多个测试用例无法并发运行,可能产生数据污染。
- 潜在内存泄露:如果单例中持有大量资源且没有及时释放,可能导致内存泄漏。
实现:
package mainimport ("fmt""sync"
)type Singleton struct {// 可能包含一些属性
}var instance *Singleton
var once sync.Oncefunc GetInstance() *Singleton {once.Do(func() {instance = &Singleton{}})return instance
}func main() {s1 := GetInstance()s2 := GetInstance()fmt.Println(s1 == s2) // true
}
二、工厂模式(Factory)
简介:
工厂模式用于创建对象的实例,但不暴露具体的创建逻辑,它通过接口来解耦对象的创建和使用。
使用场景:
- 构建复杂对象:如果对象创建过程复杂且有多种变体,使用工厂可以贱货创建逻辑。
- 接口实例化:当代码中涉及多个实现相同接口的结构体时,使用工厂可以屏蔽具体实现,方便切换。
- 减少重复代码:如果对象创建涉及大量重复逻辑,工厂方法可以封装这些逻辑。
- 依赖注入(DI)和解耦:使用工厂可以避免代码中直接依赖具体实现类,提升代码灵活性。
- 面向接口编程:在某昔日场景下需要根据配置或运行时条件来创建不同的实例。
优点:
- 解耦性高:工厂方法将对象创建与对象使用分离,调用者无需关心对象的具体创建过程。
- 符合开闭原则:增加新产品时,只需增加新的工厂方法,而无需修改原有代码,减少了对现有代码的侵入。
- 增强代码复用性:工厂方法可以复用已有的创建逻辑,避免代码重复。
- 代码结构清晰:通过工厂模式管理对象创建逻辑,使代码结构更加清晰和规范。
- 便于扩展和维护:由于工厂模式使用接口和多态特性,当需要新增类型时,不影响原有代码。
缺点:
- 复杂性增加:简单场景下使用工厂模式多此一举,反而增加了代码复杂度。
- 不适用于简单对象:如果对象创建很简单,工厂模式会引入不必要的抽象,降低代码可读性。
- 难以追踪:工厂方法隐藏了具体实现,可能让代码调用链变长,增加调试难度。
- 类爆炸问题:如果产品种类繁多,则每种产品都需要一个对应的工厂类,导致类的数量大幅增加。
实现:
简单工厂模式:适用对象较少创建、逻辑简单的场景。
package mainimport ("fmt"
)// 通知接口
type Notifier interface {Notify(message string)
}// 邮件通知
type EmailNotifier struct{}func (e *EmailNotifier) Notify(message string) {fmt.Println("Email Notification:", message)
}// 短信通知
type SMSNotifier struct{}func (s *SMSNotifier) Notify(message string) {fmt.Println("SMS Notification:", message)
}// 工厂函数
func NewNotifier(notifyType string) Notifier {switch notifyType {case "email":return &EmailNotifier{}case "sms":return &SMSNotifier{}default:return nil}
}func main() {notifier := NewNotifier("email")if notifier != nil {notifier.Notify("Hello via Email!")}notifier = NewNotifier("sms")if notifier != nil {notifier.Notify("Hello via SMS!")}
}
三、策略模式(Strategy Pattern)
简介:
一种行为设计模式,旨在将一组算法封装到独立的类中,使它们可以互相替换,通过使用策略模式,算法的变化不会影响使用算法的上下文代码。策略模式在Go语言中尤为常见,因为接口和结构体组合的特性使得实现即灵活又高效。
使用场景:
- 算法族:有多个可替换算法的场景,例如加密、排序。
- 业务规则变化频繁:例如支付策略、折扣策略。
- 避免使用条件语句:如大量
if-else
或switch
判断的地方。
优点:
- 灵活性:可以在运行时动态更改策略。
- 代码复用:不同算法独立封装,避免了条件语句的堆叠。
- 遵循开闭原则:添加新策略时无需修改上下文类。
缺点:
- 复杂性:每个策略需要创建一个类或结构体,增加代码量。
- 策略暴漏:客户端需要知道有哪些策略才能进行选择。
实现:
package mainimport "fmt"// 策略接口
type Strategy interface {Execute(a, b int) int
}// 加法策略
type AddStrategy struct{}func (s AddStrategy) Execute(a, b int) int {return a + b
}// 乘法策略
type MultiplyStrategy struct{}func (s MultiplyStrategy) Execute(a, b int) int {return a * b
}// 上下文结构体
type Context struct {strategy Strategy
}// 设置策略
func (c *Context) SetStrategy(strategy Strategy) {c.strategy = strategy
}// 执行策略
func (c *Context) ExecuteStrategy(a, b int) int {return c.strategy.Execute(a, b)
}func main() {context := Context{}// 使用加法策略context.SetStrategy(AddStrategy{})result := context.ExecuteStrategy(5, 3)fmt.Println("加法策略结果:", result) // 输出:8// 使用乘法策略context.SetStrategy(MultiplyStrategy{})result = context.ExecuteStrategy(5, 3)fmt.Println("乘法策略结果:", result) // 输出:15
}
四、观察者模式(Observer Pattern)
简介:
一种行为设计模式,允许对象在其状态发生更改时通知其他依赖对象。它定义了一种一对多的依赖关系,一个对象(主题/被观察者)状态变化时,所有依赖者(观察者)都会收到通知并自动更新。
使用场景:
- 事件驱动系统:如GUI事件监听、消息广播系统。
- 订阅-发布系统:如新闻发布、股票行情更新。
- 监控系统:如服务健康状态监控和报警。
优点:
- 解耦:主题和观察者之间的耦合性低,便于独立扩展。
- 灵活性:可以在运行时动态添加和删除观察者。
- 实时更新:状态变化时自动通知观察者,符合实时性需求。
缺点:
- 通知滞后:当观察者数量较多时,通知操作可能会有一定延迟。
- 内存泄露风险:如果没有正确管理观察者的注销,可能会导致内存泄漏。
- 调试难度较大:链式调用可能增加排查时问题的复杂性。
实现:
package mainimport "fmt"// 观察者接口
type Observer interface {Update(message string)
}// 主题接口
type Subject interface {Register(observer Observer)Unregister(observer Observer)NotifyAll(message string)
}// 具体主题
type NewsPublisher struct {observers []Observer
}// 注册观察者
func (n *NewsPublisher) Register(observer Observer) {n.observers = append(n.observers, observer)
}// 注销观察者
func (n *NewsPublisher) Unregister(observer Observer) {for i, obs := range n.observers {if obs == observer {n.observers = append(n.observers[:i], n.observers[i+1:]...)break}}
}// 通知所有观察者
func (n *NewsPublisher) NotifyAll(message string) {for _, observer := range n.observers {observer.Update(message)}
}// 具体观察者
type NewsSubscriber struct {name string
}// 接收更新通知
func (n *NewsSubscriber) Update(message string) {fmt.Printf("[%s] 收到新闻更新:%s\n", n.name, message)
}// 创建新的观察者
func NewSubscriber(name string) *NewsSubscriber {return &NewsSubscriber{name: name}
}func main() {// 创建新闻发布者(主题) 隐式使用// 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)
简介:
一种结构型设计模式,它通过一个代理对象来控制对目标对象的访问。代理对象可以在客户端和真实对象之间进行一些操作,比如权限控制、懒加载、日志记录、缓存等,特别适合增强现有类的功能而无需修改原有代码。
使用场景:
- 远程代理:使用代理来控制对远程服务的访问。
- 虚拟代理:延迟初始化较为复杂的对象。
- 安全代理:检查权限,只有合法用户才能访问。
- 只能引用代理:自动进行医用计数和资源管理。
优点:
- 职责分离:代理对象负责处理非核心业务(如日志记录),核心业务由真实对象完成。
- 灵活性强:可以动态地将额外操作附加到真实对象上。
- 曾强功能:在不修改原始类的情况下增加新功能。
缺点:
- 开销增加:由于增加了代理对象,性能有一定损耗。
- 代码复杂:增加了代码复杂性和维护难度。
实现:
package mainimport ("fmt""time"
)// 抽象接口(Subject)
type BankAccount interface {Deposit(amount float64)Withdraw(amount float64)GetBalance() float64
}// 实际对象(RealSubject):银行账户
type RealBankAccount struct {balance float64
}func (r *RealBankAccount) Deposit(amount float64) {r.balance += amountfmt.Printf("存入:%.2f 元,当前余额:%.2f 元\n", amount, r.balance)
}func (r *RealBankAccount) Withdraw(amount float64) {if amount > r.balance {fmt.Println("余额不足,取款失败!")return}r.balance -= amountfmt.Printf("取出:%.2f 元,当前余额:%.2f 元\n", amount, r.balance)
}func (r *RealBankAccount) GetBalance() float64 {return r.balance
}// 代理对象(Proxy):日志代理
type LoggingProxy struct {realAccount BankAccount
}func NewLoggingProxy(realAccount BankAccount) *LoggingProxy {return &LoggingProxy{realAccount: realAccount}
}func (p *LoggingProxy) Deposit(amount float64) {fmt.Printf("[%s] 正在进行存款操作...\n", time.Now().Format("2006-01-02 15:04:05"))p.realAccount.Deposit(amount)
}func (p *LoggingProxy) Withdraw(amount float64) {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)return balance
}// 客户端代码
func main() {// 创建实际银行账户realAccount := &RealBankAccount{}// 使用代理来包装实际账户proxy := NewLoggingProxy(realAccount)// 通过代理进行操作proxy.Deposit(1000)proxy.Withdraw(300)proxy.GetBalance()
}
六、装饰器模式
简介:
一种结构型设计模式,允许在不修改对象结构的情况下动态地为对象添加新功能。
使用场景:
- 功能增强:为对象动态添加功能。
- 替代子类继承:通过组合而非继承来扩展功能。
- 职责划分:使每个装饰器负责特定功能,符合单一职责原则。
装饰器模式的核心思想:
- 组件接口(Component):定义一个可以被装饰的对象接口。
- 具体组件(Concrete Component):实现基础功能。
- 装饰器接口(Decorator):持有组件接口的引用,且具有相同的方法。
- 具体装饰器(Concrete Decorator):扩展组件的功能。
优点:
- 灵活性高:可以通过多个装饰器动态组合新功能。
- 符合开闭原则:可以随时添加新装饰器而不影响原有代码。
- 职责单一:每个装饰器只负责一个特定功能。
缺点:
- 装饰链过长:可能导致结构复杂,难以维护。
- 性能开销:多层嵌套会带来性能损耗。
实现:
package mainimport ("fmt"
)// Component 接口:咖啡饮品
type Beverage interface {GetDescription() stringCost() float64
}// 具体组件:基础咖啡
type Espresso struct{}func (e *Espresso) GetDescription() string {return "Espresso"
}func (e *Espresso) Cost() float64 {return 15.0
}// 装饰器基类:实现 Beverage 接口
type CondimentDecorator struct {beverage Beverage
}func (c *CondimentDecorator) GetDescription() string {return c.beverage.GetDescription()
}func (c *CondimentDecorator) Cost() float64 {return c.beverage.Cost()
}// 具体装饰器:牛奶
type Milk struct {CondimentDecorator
}func NewMilk(beverage Beverage) *Milk {return &Milk{CondimentDecorator{beverage}}
}func (m *Milk) GetDescription() string {return m.beverage.GetDescription() + ", Milk"
}func (m *Milk) Cost() float64 {return m.beverage.Cost() + 3.5
}// 具体装饰器:糖
type Sugar struct {CondimentDecorator
}func NewSugar(beverage Beverage) *Sugar {return &Sugar{CondimentDecorator{beverage}}
}func (s *Sugar) GetDescription() string {return s.beverage.GetDescription() + ", Sugar"
}func (s *Sugar) Cost() float64 {return s.beverage.Cost() + 1.0
}// 客户端代码
func main() {// 创建基础咖啡var beverage Beverage = &Espresso{}fmt.Printf("饮品:%s,价格:%.2f 元\n", beverage.GetDescription(), beverage.Cost())// 加牛奶beverage = NewMilk(beverage)fmt.Printf("饮品:%s,价格:%.2f 元\n", beverage.GetDescription(), beverage.Cost())// 再加糖beverage = NewSugar(beverage)fmt.Printf("饮品:%s,价格:%.2f 元\n", beverage.GetDescription(), beverage.Cost())
}
装饰器模式和代理模式对比
特性 | 装饰器模式 | 代理模式 |
---|---|---|
主要目的 | 动态扩展功能 | 控制对对象的访问 |
结构特点 | 组合多个装饰器形成链 | 代理对象持有实际对象的引用 |
典型应用场景 | 日志、性能监控、权限校验、增强对象功能 | 远程代理、虚拟代理、安全代理、缓存代理 |
七、适配器模式(Adapter Pattern)
简介:
一种结构型设计模式,它通过两个不兼容的接口提供一个适配器,使得它们能够一起工作。适配器模式可以将一个接口转换为客户端期望的另一个接口,目的时让不兼容的接口能过够合作。
使用场景:
- 多重接口适配(统一接口标准):在一个系统中,你可能需要使用多个不兼容的接口,而这些接口都执行类似的操作。适配器模式可以帮助你统一这些接口,使得系统中其他部分可以通过相同的接口与它们交互。
- 兼容性问题(与现有系统兼容):如果你正在集成一个第三方库,或者使用一个遗留系统,而该系统的接口与现有系统不兼容,适配器模式可以帮助你转换这些不兼容的接口,使得它们能够顺利协作。
- 第三方库接口的适配(外部API整合):当使用第三方库时,这些库通常提供不同的接口,而你希望用一个统一的接口访问这些库。适配器模式可以将第三方库的接口适配为你项目中需要的标准接口。
- 接口升级或变化:当你需要对现有接口进行修改,但又不希望影响到客户端的代码时,适配器模式可以帮助你维护原接口的兼容性,同时在背后对接口进行改造或升级。
- 不同硬件或设备的适配:当你在开发跨平台应用或者硬件交互时,可能需要适配不同硬件或设备的接口。适配器模式可以帮助将不同硬件提供的接口适配到你应用需要的标准接口上。
- 系统迁移或重构:在系统重构的过程中,可能会涉及到接口的更改,而你又希望让现有代码与新代码兼容。适配器模式能够在过渡期间无缝衔接新旧系统的接口。
- 替代继承的场景(类适配):如果一个类不适用于继承的方式,或者你不想改变原有类的结构,可以使用适配器模式代替继承来扩展功能。
- API或数据协议的适配:不同的系统或组件之间可能使用不同的数据格式或协议,适配器模式能够在这些不同的格式之间提供一个桥梁。
适配器模式的核心思想
- 目标接口(Target):客户端期望使用的接口。
- 源接口(Adaptee):需要适配的现有接口,它的方法不能直接与客户端使用的接口兼容。
- 适配器(Adapter):将源接口转换为目标接口,使得客户端可以通过目标接口使用源接口的功能。
优点:
- 兼容不兼容的接口:使得本来不兼容的接口通过适配器能够协同工作。
- 符合开闭原则:通过适配器可以在不修改原有类的情况下,改变接口的使用方式。
- 解耦:客户端不需要知道适配器的实现,只需要依赖目标接口。
缺点:
- 增加代码复杂性:适配器模式会引入额外的类和对象,可能增加代码的复杂性。
- 性能开销:在适配器模式中,通常有额外的间接调用,可能导致轻微的性能损失。
实现:
package mainimport "fmt"// 目标接口(Target):要求的电源接口
type PowerOutlet interface {SupplyPower() string
}// 源接口(Adaptee):我们现有的电源接口
type TwoPinSocket struct{}func (s *TwoPinSocket) ProvidePower() string {return "提供 220V 电流"
}// 适配器(Adapter):将现有电源接口转换为目标接口
type Adapter struct {socket *TwoPinSocket
}// 适配器的方法:使其实现目标接口
func (a *Adapter) SupplyPower() string {return a.socket.ProvidePower()
}// 客户端代码
func main() {// 使用现有的 2 针电源插座(不符合目标接口)twoPinSocket := &TwoPinSocket{}// 通过适配器将其转换为目标接口adapter := &Adapter{socket: twoPinSocket}// 客户端通过目标接口使用适配后的电源fmt.Println("设备电源:", adapter.SupplyPower())
}
适配器模式与代理模式的对比
特性 | 适配器模式 | 代理模式 |
---|---|---|
主要目的 | 使接口兼容并进行转换,适配不同接口的类 | 控制对目标对象的访问,通常是延迟或虚拟化操作。 |
结构特点 | 客户端和目标接口之间通过适配器进行转换 | 代理对象持有实际对象的引用,进行控制访问 |
典型应用场景 | 使得不兼容的类能够协作,转换接口 | 控制对实际对象的访问(如延迟加载、远程调用等) |
相关文章:
Go常用的设计模式
Go常用的设计模式 常见的设计模式,如 单例模式、工厂模式、策略模式、观察者模式、代理模式、装饰器模式 和 适配器模式 都可以在 Go 中实现,适用于不同的开发需求。 这些设计模式不仅能帮助你编写结构清晰、可维护的代码,还能让你更好地应…...
复现文献中的三维重建图像生成,包括训练、推理和可视化
要复现《One - 2 - 3 - 45 Fast Single Image to 3D Objects with Consistent Multi - View Generation and 3D Diffusion (CVPR)2024》文献中的三维重建图像生成,包括训练、推理和可视化,并且确保代码能正常运行,下面是基本的实现步骤和示例…...
day17 学习笔记
文章目录 前言一、数组的增删改查1.resize函数2.append函数3.insert函数4.delete函数5.argwhere函数6.unique函数 二、统计函数1.amax,amin函数2.ptp函数3.median函数4.mean函数5.average函数6.var,std函数 前言 通过今天的学习,我掌握了num…...
Mysql练习题
先创建对应数据表 #先创建表 #学生表 Student create table Student(SId varchar(10),Sname varchar(10),Sage datetime,Ssex varchar(10)); insert into Student values(01 , 赵雷 , 1990-01-01 , 男); insert into Student values(02 , 钱电 , 1990-12-21 , 男); insert int…...
torch不能使用cuda的解决方案
遇到了这样的报错,说明 torch不能使用cuda 反思 我频繁地尝试安装不同的 nvdia 驱动,浪费了很多时间。因为我的错误地认为nvidia会自带cuda,其实cuda需要单独安装。 还有我的torch是cpu版本的,即使nvidia cuda安装了࿰…...
Python 循环全解析:从语法到实战的进阶之路
一、问答题 (1)下面的循环体被重复了多少次?每次循环的输出结果是什么? i1 while i < 10:if i % 2 0:print(i)死循环,没有输出结果 i1 while i < 10:if i % 2 0:print(i)i l死循环,没有输出结果 i 1 while i< 10…...
代码随想录算法训练营--打卡day3
复习:标注感叹号的需要在电脑上重新做几遍 一.两两交换链表中的节点!! 1.题目链接 24. 两两交换链表中的节点 - 力扣(LeetCode) 2.思路 画图 3.代码 class Solution {public ListNode swapPairs(ListNode head) …...
ubuntu 安装mysql
在 Ubuntu 系统中安装 MySQL 的步骤如下: 步骤 1:更新软件包列表 sudo apt update步骤 2:安装 MySQL 服务器 sudo apt install mysql-server -yUbuntu 22.04/20.04 默认安装 MySQL 8.0,早期版本可能默认使用 MariaDB。 如果需要…...
用Python实现资本资产定价模型(CAPM)
使用 Python 计算资本资产定价模型(CAPM)并获取贝塔系数(β)。 步骤 1:导入必要的库 import pandas as pd import yfinance as yf import statsmodels.api as sm import matplotlib.pyplot as plt 步骤 2࿱…...
Conda配置Python环境
1. 安装 Conda 选择发行版: Anaconda:适合需要预装大量科学计算包的用户(体积较大)。 Miniconda:轻量版,仅包含 Conda 和 Python(推荐自行安装所需包)。 验证安装: co…...
Redisson延迟队列实战:分布式系统中的“时间管理者“
目录 引言:延迟队列的魅力与应用 什么是Redisson延迟队列? 技术原理与工作机制 应用场景 环境准备:搭建基础 Maven依赖配置 Redisson客户端配置 延迟队列实现:核心代码 工作原理深度解析 数据模型与存储结构 元素流转过…...
国产化适配 - YashanDB、达梦数据库与MySQL 的兼容性及技术选型对比分析
根据知识库信息,以下是 YashanDB、达梦数据库与MySQL 的兼容性及技术选型对比分析: 1. YashanDB 与 MySQL 兼容性 协议与语法兼容 : YashanDB 100%兼容 MySQL 5.7协议 的常用命令(如 SELECT、INSERT),但…...
从0开始——在PlatformIO下开展STM32单片机的HAL库函数编程指南
目录 前言 编写时钟初始化 实现Systicks_Handler,完成HAL库的时基更新 编写驱动测试 前言 笔者最开始的尝试是在2025年的寒假,准备向PlatformIO迁移HAL库,注意,截止到目前,PlatformIO对HAL库的支持已经非常完善了。…...
Python小练习系列 Vol.9:杨辉三角生成(数组构建 + 数学组合)
🧠 Python小练习系列 Vol.9:杨辉三角生成(数组构建 数学组合) 🔺 本期我们带来一道简洁却优雅的经典练习 —— 生成杨辉三角,是训练数组操作与组合思想的绝佳题目! 🧩 一、题目描述…...
Webview详解(下)
第三阶段:性能优化 加载速度优化 缓存策略 缓存策略可以显著减少网络请求,提升页面加载速度。常用的缓存策略包括 HTTP 缓存和本地资源预加载。 1. HTTP 缓存 HTTP 缓存利用 HTTP 协议中的缓存机制(如 Cache-Control、ETag 等࿰…...
scss基础用法
SCSS(Sassy CSS)是Sass的增强版本,作为CSS的预处理器,它提供了多种功能来提高代码的可维护性和效率。以下是SCSS的基础用法: 变量(Variables) 用于存储常用的值,如颜色、字体大小等。…...
知能行每日综测
题目1 自己的做法 答案 题目2 自己的 答案 题目3 注意:这道做错了,你们可以看看我哪里错了 题目4 我的 答案 题目5 没思路,不会做 已更改 题目6 答案 第七题 我的 不会 现在补综测最后一个...
c++ vs和g++下的string结构
话不多说进入正题.注:下述结构是在32位平台下进行验证,32位平台下指针占4个字节. vs下string的结构 string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义 string中字符串的存储空间:(联合体的…...
海量数据处理
1.海量数据处理问题 给两个文件,分别有100亿个query,只有1G内存,如何找到两个文件交集? 解决方案一: 可以先用布隆过滤器,一个文件的query放进布隆过滤器,另一个文件依次查找,在的…...
洛谷题单1-P5706 【深基2.例8】再分肥宅水-python-流程图重构
题目描述 现在有 t t t 毫升肥宅快乐水,要均分给 n n n 名同学。每名同学需要 2 2 2 个杯子。现在想知道每名同学可以获得多少毫升饮料(严格精确到小数点后 3 3 3 位),以及一共需要多少个杯子。 输入格式 输入一个实数 t …...
【HarmonyOS 5】初学者如何高效的学习鸿蒙?
【HarmonyOS 5】初学者如何高效的学习鸿蒙? 一、前言 在全球科技格局风云变幻的当下,谷歌安卓系统的管控逐步收紧,加之国际形势愈发复杂,打造中国人自主的操作系统,已成为时代发展的必然要求,这不仅是突破…...
Java NIO之FileChannel 详解
关键点说明 文件打开选项: StandardOpenOption.CREATE - 文件不存在时创建 StandardOpenOption.READ/WRITE - 读写权限 StandardOpenOption.APPEND - 追加模式 StandardOpenOption.TRUNCATE_EXISTING - 清空已存在文件 缓冲区操作: ByteBuffer.wrap…...
数据可视化(matplotlib)-------图表样式美化
目录 一、图表样式概述 (一)、默认图表样式 (二)、图表样式修改 1、局部修改 2、全局修改 二、使用颜色 (一)、使用基础颜色 1、单词缩写或单词表示的颜色 2、十六进制/HTML模式表示的颜色 3、RGB…...
Go 语言中,关于客户端初始化的最佳实践
在 Go 语言中,关于客户端初始化的最佳实践确实需要注意以下几点: 全局单例模式是推荐做法,尤其对于需要保持长连接或需要复用资源的客户端(如数据库、Redis、HTTP 客户端等)并发安全是必须保证的,需要确保…...
MyBatis的第一天笔记
1. MyBatis 概述 1.1 什么是框架 框架是对通用代码的封装,提前写好了一堆接口和类,可以直接引入使用框架一般以jar包形式存在Java常用框架:SSM三大框架(Spring SpringMVC MyBatis)、SpringBoot、SpringCloud等 1.…...
区块链赋能,为木材货场 “智” 造未来
区块链赋能,为木材货场 “智” 造未来 在当今数字化浪潮席卷的时代,软件开发公司不断探索创新,为各行业带来高效、智能的解决方案。今天,让我们聚焦于一家软件开发公司的杰出成果 —— 区块链木材货场服务平台,深入了…...
IvorySQL:兼容Oracle数据库的开源PostgreSQL
今天给大家介绍一款基于 PostgreSQL 开发、兼容 Oracle 数据库的国产开源关系型数据库管理系统:IvorySQL。 IvorySQL 由商瀚高软件提供支持,主要的功能特性包括: 完全兼容 PostgreSQL:IvorySQL 基于 PostgreSQL 内核开发…...
Python 序列构成的数组(切片)
切片 在 Python 里,像列表(list)、元组(tuple)和字符串(str)这类 序列类型都支持切片操作,但是实际上切片操作比人们所想象的要强大 很多。 这一节主要讨论的是这些高级切片形式的…...
Pre-flash和Main flash
在相机拍照过程中,Pre-flash(预闪光) 和 Main flash(主闪光) 是常见的两种闪光灯使用模式,通常用于提高低光环境下的拍摄质量,尤其在自动曝光(AE)和自动对焦(…...
【区块链安全 | 第十篇】智能合约概述
部分内容与前文互补。 文章目录 一个简单的智能合约子货币(Subcurrency)示例区块链基础交易区块预编译合约 一个简单的智能合约 我们从一个基础示例开始,该示例用于设置变量的值,并允许其他合约访问它。 // SPDX-License-Identi…...
判断质数及其优化方法
判断质数(素数)及其优化方法 质数是指 大于1的自然数,且 只有1和它本身两个正约数。以下是几种判断方法及其优化策略。 目录 基础方法(试除法)优化1:仅检查到√n优化2:跳过偶数优化3ÿ…...
【源码阅读/Vue Flask前后端】简历数据查询功能
目录 一、Flask后端部分modelServiceroute 二、Vue前端部分index.js main.vue功能界面templatescriptstyle 一般就是三个层面,model层面用来建立数据库的字段,service用来对model进行操作,写一些数据库操作的代码,route就是具体的…...
R语言对偏态换数据进行转换(对数、平方根、立方根)
我们进行研究的时候经常会遇见偏态数据,数据转换是统计分析和数据预处理中的一项基本技术。使用 R 时,了解如何正确转换数据有助于满足统计假设、标准化分布并提高分析的准确性。在 R 中实现和可视化最常见的数据转换:对数、平方根和立方根转…...
链表(C++)
这是本人第二次学习链表,第一次学习链表是在大一上的C语言课上,首次接触,感到有些难;第二次是在大一下学习数据结构时(就是这次),使用C再次理解链表。同时,这也是开启数据结构学习写…...
算法-前缀和与差分
一、前缀和(Prefix Sum) 1. 核心思想 前缀和是一种预处理数组的方法,通过预先计算并存储数组的前缀和,使得后续的区间和查询可以在**O(1)**时间内完成。 2. 定义 给定数组 nums,前缀和数组 prefixSum 的每个元素 p…...
网关接口超时?用Java实现接口快速返回,后台继续执行的方法
网关接口超时?用Java实现接口快速返回,后台继续执行的方法 在开发过程中,我们经常会遇到网关接口由于超时限制而导致请求失败的情况。然而,有些接口本身就需要较长时间来执行任务,这时我们不能简单地增加超时时间&…...
HTTP---基础知识
天天开心!!! 文章目录 一、HTTP基本概念1. 什么是HTTP,又有什么用?2. 一次HTTP请求的过程3.HTTP的协议头4.POST和GET的区别5. HTTP状态码6.HTTP的优缺点 二、HTTP的版本演进1.各个版本的应用场景2、注意要点 三、HTTP与…...
python基础学习三(元组及字符串的使用)
文章目录 元组什么是元组元组的创建方式为什么要将元组设计成不可变序列元组的遍历集合集合的相关操作集合操作集合的数学操作集合生成式列表,字典,元组,集合总结 字符串字符串的驻留机制判断字符串的操作方法字符串的比较操作字符串的切片操…...
c#winform,倒鸭子字幕效果,typemonkey字幕效果,抖音瀑布流字幕效果
不废话 直接上效果图 C# winform 开发抖音的瀑布流字幕。 也是typemonkey插件字幕效果 或者咱再网上常说的倒鸭子字幕效果 主要功能 1,软件可以自定义添加字幕内容 2,软件可以添加字幕显示的时间区间 3,可以自定义字幕颜色,可以随…...
1、C51单片机(STC8G2K64S4)串口实验
一、串口1接线图 1、下面是单片机外接电路图,P30,P31分别用于RXD和TXD功能引脚 2、我们来查看单片机手册 串口1需要设置的寄存器 串口1的功能脚配置选择位,看电路图选择的是P3.0,P3.1。 3、串口1:SCON控制寄存器 设置为0x50:0101 0000。&a…...
ue材质学习感想总结笔记
2025 - 3 - 27 1.1 加法 对TexCoord上的每一个像素加上一个值,如果加上0.1,0.1, 那么左上角原来0,0的位置变成了0.1,0.1 右上角就变成了1.1,1.1,那么原来0,0的位置就去到了左上角左上边,所以图像往左上偏移。 总而言…...
MFC TRACE 宏的使用说明
书籍:《Visual C 2017从入门到精通》的2.7 字符串 环境:visual studio 2022 内容:几个字符串类型->(将单字节char*转换为宽字节wchar_t *)(将宽字节wchar_t* 转换为单字节char *) 问题&am…...
latex笔记
1、基本结构 \documentclass[a4paper, 12pt]{article} %文档类型 \begin{document}\title{My First Document}\author{My Name}\date{\today}\maketitleA sentence of text. \end{document}2、带有章、节、小节的结构 \documentclass[a4paper, 12pt]{article}\begin{document…...
Unity编辑器功能及拓展(3) —[Attribute]特性
在 Unity 中,[Attribute]格式的特性是用于扩展编辑器功能、控制序列化行为和调整 Inspector 显示,进行编辑器拓展的核心工具。 一.基础编辑器拓展 1.基础序列化控制 1.[SerializeField] 强制显示私有变量到Inspector 2.[HideInInspector] 隐藏该字段在Inspect…...
Rust基础语法
以下是 Rust 语言基础语法的核心要点,结合与 JavaScript 的对比,帮助前端开发者快速掌握核心概念: 一、变量与常量 1. 变量声明 Rust:变量默认不可变,需用 mut 显式声明可变性。let x 5; // 不可变变量 le…...
<tauri><rust><GUI>基于rust和tauri,实现一个大寰电爪PGHL(串口设备)定制化控制程序
前言 本文是基于rust和tauri,由于tauri是前、后端结合的GUI框架,既可以直接生成包含前端代码的文件,也可以在已有的前端项目上集成tauri框架,将前端页面化为桌面GUI。 环境配置 系统:windows 10平台:visual studio code语言:rust、javascript库:tauri2.0概述 本文是…...
Sentinel 相关知识点
Sentinel 实现原理? Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护等多个维度来帮助开发者保障微服务的稳定性。以下是 Sentinel 的实现原理: 核心概念 资源&…...
DFS飞机降落
问题描述 NN 架飞机准备降落到某个只有一条跑道的机场。其中第 ii 架飞机在 TiTi 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 DiDi 个单位时间,即它最早可以于 TiTi 时刻开始降落,最晚可以于 TiDiTiDi 时刻开始降落。降落…...
SpringCould微服务架构之Docker(5)
Docker的基本操作: 镜像相关命令: 1.镜像名称一般分两部分组成:[repository]:[tag]。 2. 在没有指定tag时,默认是latest,代表着最新版本的镜像。 镜像命令的案例: 镜像操作常用的命令: dock…...
音乐webpack(通杀webpack-1)
本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 本文章未经许可…...