Go中实现代理模式需定义统一接口(如UserService),真实对象(RealUserService)专注业务逻辑,代理对象通过组合实现相同接口并添加日志、权限等横切逻辑,调用方无感知。
在 Go 中实现代理模式,核心是通过一个代理对象来控制对真实对象的访问,并在访问前后插入自定义逻辑(如日志、权限校验、缓存、重试等)。Go 没有原生的类继承和接口强制实现机制,但凭借接口(interface)和组合(composition),可以简洁、灵活地实现代理模式。
代理模式的前提是“真实对象”和“代理对象”对外提供相同行为。Go 中用接口抽象这一契约:
// 定义业务能力接口(例如:用户服务)
type UserService interface {
GetUser(id int) (*User, error)
CreateUser(name string) (int, error)
}
type User struct {
ID int
Name string
}
只要真实服务和代理都实现 UserService,调用方无需感知差异,符合里氏替换原则。
真实对象只做它该做的事,不掺杂横切关注点:
type RealUserService struct{}
func (r *RealUserService) GetUser(id int) (*User, error) {
// 模拟数据库查询
if id <= 0 {
return nil, fmt.Errorf("invalid id")
}
return &User{ID: id, Name: "Alice"}, nil
}
func (r *RealUserService) CreateUser(name string) (int, error) {
// 模拟创建并返回 ID
return 123, nil
}
代理结构体持有真实对象引用,并实现相同接口。每个方法中可自由添加前置(如鉴权、日志)、后置(如审计、缓存写入)或异常处理逻辑:
type UserServiceProxy struct {
realService UserService
logger *log.Logger
}
func NewUserServiceProxy(real UserService, logger *log.Logger) *UserServiceProxy {
return &UserServiceProxy{
realService: real,
logger: logger,
}
}
func (p *UserServiceProxy) GetUser(id int) (*User, error) {
p.logger.Printf("[BEFORE] GetUser called with id=%d", id)
user, err := p.realService.GetUser(id) // 调用真实对象
if err != nil {
p.logger.Printf("[AFTER-ERROR] GetUser failed: %v", err)
return nil, err
}
p.logger.Printf("[AFTER] GetUser succeeded, found user: %+v", user)
return user, nil
}
func (
p *UserServiceProxy) CreateUser(name string) (int, error) {
p.logger.Printf("[BEFORE] CreateUser called with name=%q", name)
id, err := p.realService.CreateUser(name)
if err == nil {
p.logger.Printf("[AFTER] CreateUser succeeded, assigned ID=%d", id)
} else {
p.logger.Printf("[AFTER-ERROR] CreateUser failed: %v", err)
}
return id, err
}
关键点:
客户端代码完全不用改,只需把真实对象换成代理实例:
func main() {
real := &RealUserService{}
logger := log.New(os.Stdout, "[PROXY] ", log.LstdFlags)
proxy := NewUserServiceProxy(real, logger)
// 调用方无感知 —— 仍用 UserService 接口
user, _ := proxy.GetUser(42)
fmt.Printf("Retrieved: %+v\n", user)
id, _ := proxy.CreateUser("Bob")
fmt.Printf("Created with ID: %d\n", id)
}
输出示例:
[PROXY] [BEFORE] GetUser called with id=42
[PROXY] [AFTER] GetUser succeeded, found user: &{ID:42 Name:Alice}
Retrieved: &{ID:42 Name:Alice}
[PROXY] [BEFORE] CreateUser called with name="Bob"
[PROXY] [AFTER] CreateUser succeeded, assigned ID=123
Created with ID: 123
不复杂但容易忽略
# go
# golang
# 结构体
# 继承
# 接口
# Interface
# 对象
# 这一
# 横切
# 只需
# 并在
# 自定义
# 只做
# 该做
# 重试
# 也需
# 复用
相关文章:
交易网站制作流程,我想开通一个网站,注册一个交易网址,需要那些手续?
制作网站的软件免费下载,免费制作app哪个平台好?
打鱼网站制作软件,波克捕鱼官方号怎么注册?
如何基于云服务器快速搭建网站及云盘系统?
制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
用v-html解决Vue.js渲染中html标签不被解析的问题
如何快速搭建高效简练网站?
如何确保西部建站助手FTP传输的安全性?
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
如何在Windows虚拟主机上快速搭建网站?
如何通过万网虚拟主机快速搭建网站?
如何在IIS7中新建站点?详细步骤解析
如何快速查询网址的建站时间与历史轨迹?
建站主机选购指南:核心配置与性价比推荐解析
如何获取免费开源的自助建站系统源码?
建站之星logo尺寸如何设置最合适?
黑客入侵网站服务器的常见手法有哪些?
IOS倒计时设置UIButton标题title的抖动问题
测试制作网站有哪些,测试性取向的权威测试或者网站?
建站之星Pro快速搭建教程:模板选择与功能配置指南
建站主机CVM配置优化、SEO策略与性能提升指南
建站主机类型有哪些?如何正确选型
头像制作网站在线制作软件,dw网页背景图像怎么设置?
南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?
Python路径拼接规范_跨平台处理说明【指导】
网站制作多少钱一个,建一个论坛网站大约需要多少钱?
外贸公司网站制作,外贸网站建设一般有哪些步骤?
道歉网站制作流程,世纪佳缘致歉小吴事件,相亲网站身份信息伪造该如何稽查?
网站企业制作流程,用什么语言做企业网站比较好?
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
网站制作知乎推荐,想做自己的网站用什么工具比较好?
网站制作专业公司有哪些,如何制作一个企业网站,建设网站的基本步骤有哪些?
香港服务器如何优化才能显著提升网站加载速度?
正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?
如何在建站主机中优化服务器配置?
深圳网站制作平台,深圳市做网站好的公司有哪些?
佛山网站制作系统,佛山企业变更地址网上办理步骤?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
专业制作网站的公司哪家好,建立一个公司网站的费用.有哪些部分,分别要多少钱?
建站之星展会模板:智能建站与自助搭建高效解决方案
天河区网站制作公司,广州天河区如何办理身份证?需要什么资料有预约的网站吗?
如何通过商城免费建站系统源码自定义网站主题?
公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?
临沂网站制作公司有哪些,临沂第四中学官网?
新网站制作渠道有哪些,跪求一个无线渠道比较强的小说网站,我要发表小说?
如何快速配置高效服务器建站软件?
如何在万网开始建站?分步指南解析
上海网站制作网站建设公司,建筑电工证网上查询系统入口?
济南网站制作的价格,历城一职专官方网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。