Go语言代理模式详解:概念、特点与实战示例
创作时间:
作者:
@小白创作中心
Go语言代理模式详解:概念、特点与实战示例
引用
CSDN
1.
https://blog.csdn.net/LuckyLay/article/details/145745256
代理模式是一种常用的设计模式,通过引入代理对象间接访问真实对象,从而在不修改原对象代码的前提下,控制访问或增强功能。本文将详细介绍代理模式的核心概念、特点分析、适用场景,并通过Go语言代码示例帮助读者深入理解这一模式。
一、核心概念
1. 定义
代理模式(Proxy Pattern)是一种结构型设计模式,通过引入代理对象间接访问真实对象,从而在不修改原对象代码的前提下,控制访问或增强功能(如日志、缓存、权限校验)。
2. 解决的问题
- 访问控制:限制对真实对象的直接访问(如权限校验)
- 功能扩展:在调用真实对象前后添加额外逻辑(如日志、缓存)
- 资源优化:延迟加载高开销对象(如大文件、远程服务)
3. 核心角色
- Subject(抽象主题)
定义真实对象和代理的公共接口(如
UserService
接口) - RealSubject(真实主题)
实现具体业务逻辑(如
RealUserService
处理数据库查询) - Proxy(代理)
持有真实对象的引用,并添加增强逻辑(如缓存代理
UserServiceProxy
)
4. 类图
二、特点分析
优点
- 职责分离:代理处理非核心逻辑(如日志),真实对象专注业务
- 扩展性强:新增代理不影响原有代码,符合开闭原则
- 资源保护:通过代理控制敏感操作(如权限校验)
缺点
- 性能损耗:动态代理(如反射)可能降低执行效率
- 复杂度增加:需维护代理与真实对象的关系
三、适用场景
- 权限控制:接口调用前的身份验证
- 延迟加载:按需加载大资源(如图片、文件)
- 日志监控:记录方法调用参数和结果
- 远程调用:RPC框架通过代理隐藏网络细节
四、代码示例(Go语言)
1. 文件下载代理(含权限校验)
package proxydemo
import "fmt"
// 抽象主题 文件接口
type File interface {
Download()
}
// 真实主题 真实文件
type RealFile struct {
Name string
}
func (r *RealFile) Download() {
fmt.Println("Downloading " + r.Name)
}
// 代理:文件代理
type FileProxy struct {
realFile *RealFile
userRole string
}
func NewFileProxy(filename, role string) *FileProxy {
return &FileProxy{
realFile: &RealFile{Name: filename},
userRole: role,
}
}
func (f *FileProxy) Download() {
if f.userRole == "admin" {
f.realFile.Download()
} else {
fmt.Println("You don't have permission to download " + f.realFile.Name)
}
}
func test_downloadFile(role string) {
adminFile := NewFileProxy("adminFile.txt", role)
adminFile.Download()
}
测试方法
package proxydemo
import "testing"
func Test_test_downloadFile(t *testing.T) {
type args struct {
role string
}
tests := []struct {
name string
args args
}{
{
name: "admin",
args: args{
role: "admin",
},
},
{
name: "user",
args: args{
role: "user",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
test_downloadFile(tt.args.role)
})
}
}
输出结果:
=== RUN Test_test_downloadFile
=== RUN Test_test_downloadFile/admin
Downloading adminFile.txt
=== RUN Test_test_downloadFile/user
You don't have permission to download adminFile.txt
--- PASS: Test_test_downloadFile (0.00s)
--- PASS: Test_test_downloadFile/admin (0.00s)
--- PASS: Test_test_downloadFile/user (0.00s)
PASS
2. 缓存代理(用户信息查询)
package proxydemo
import "fmt"
type UserService interface {
GetUser(id int) (string, error)
}
type RealUserService struct{}
func (r *RealUserService) GetUser(id int) (string, error) {
// 模拟从数据库中获取用户信息
return fmt.Sprintf("User%d", id), nil
}
type CachedUserService struct {
realService UserService
cache map[int]string
}
func NewCachedUserService() *CachedUserService {
return &CachedUserService{
realService: &RealUserService{},
cache: make(map[int]string),
}
}
func (c *CachedUserService) GetUser(id int) (string, error) {
if user, ok := c.cache[id]; ok {
fmt.Println("Returning user from cache")
return user, nil
}
fmt.Println("Fetching user from real service")
user, err := c.realService.GetUser(id)
if err != nil {
return "", err
}
c.cache[id] = user
return user, nil
}
func test_cache() {
cachedService := NewCachedUserService()
user, _ := cachedService.GetUser(1)
fmt.Println("User:", user)
fmt.Println("-----------------")
user, _ = cachedService.GetUser(1)
fmt.Println("User:", user)
}
输出结果
=== RUN Test_test_cache
Fetching user from real service
User: User1
-----------------
Returning user from cache
User: User1
--- PASS: Test_test_cache (0.00s)
PASS
五、高级应用
- 动态代理
Go可通过反射实现动态代理(需处理性能损耗):
func DynamicProxy(target interface{}, preHandler func()) interface{} {
val := reflect.ValueOf(target)
return reflect.New(val.Type()).Interface()
}
- 组合代理链
多个代理嵌套使用(如先鉴权再缓存):
authProxy := NewAuthProxy(userRole)
cachedProxy := NewCachedProxy(authProxy)
cachedProxy.Download()
六、与其他模式对比
模式 | 核心目标 | 关键区别 |
---|---|---|
装饰器 | 动态添加功能 | 关注功能叠加 |
适配器 | 接口转换 | 解决兼容性问题 |
代理 | 控制访问/增强前置后置逻辑 | 侧重访问限制和流程控制 |
七、总结
代理模式通过间接访问和逻辑增强,解决了以下问题:
- 安全控制:通过代理拦截非法请求
- 功能扩展:无侵入式添加日志、缓存等逻辑
- 资源优化:延迟加载降低系统开销
在Go中实现时需注意:
- 优先使用接口定义抽象主题
- 代理与真实对象需实现相同接口
- 避免过度使用动态代理(反射有性能损耗)
热门推荐
出入境要准备哪些材料?
吕祖灵签48签陈万年不第 此签详细分析
当外国友人遇上瑶族盘王节,画面是……
什么是传感器的线性度?
10分钟缩胯操,消灭假胯宽,让你腿长15公分,腰瘦5厘米!
胃肠镜VS胶囊内镜,如何选择?
Web产品升级如何清理缓存
从这个角度看待关系,你会少受很多伤
Excel中判断是否为数字的多种方法及应用案例
好好的一板药为何少一粒?这篇文章可以告诉你答案
如何定义欧洲豪门球队?阿森纳没有欧冠,维拉有欧冠,谁是豪门?
期货趋势的定义是什么?如何通过技术分析判断期货趋势?
《城市重点消防安全与火灾防控指引》在宁发布,助力提升公众安全意识
足部也要练“核心”
揭秘几何图形中的“好朋友”:探究同旁内角的奇妙关系
缺席高规格民营企业座谈会:那些民营企业家背后的故事
王者荣耀17个射手英雄的理想型辅助搭配攻略
人工智能在医疗辅助诊断中的关键问题与挑战
泉州安平桥:中古时代世界最长的跨海梁式石桥
装备制造行业向“高”攀登
发酵食品能增强免疫力吗?
苹果手机录屏功能详解及实用技巧分享
如何通过员工消防安全培训记录提升整体安全意识?
智慧污水处理厂:用科技革新传统污水处理模式
春茶选购5大标准评析
哪些坚果助力心血管健康?每天一小把,降低胆固醇的秘诀在这里!
这4种降糖药,越吃越瘦,瘦糖友还能吃吗?
方成院士:为太阳空间观测贡献“中国视角”
“延期换证” 怎么办理?
现在买新能源车仍然需要关注电池寿命,原因如下: