Go中观察者模式通过函数类型Observer和Subject结构体实现,支持注册、移除、通知,结合嵌入或组合封装业务对象,如TemperatureSensor,并可扩展泛型、异步通知与取消机制。
用 Go 实现观察者模式,核心是定义一个被观察对象(Subject)和多个观察者(Observer),当 Subject 状态变化时,自动通知所有已注册的 Observer。Go 没有内置接口继承机制,但通过接口+组合+函数类型,能简洁、高效地实现该模式。
Observer 是一个函数类型或接口,用于接收状态更新;Subject 维护观察者列表,并提供注册、移除、通知方法。
推荐使用函数类型作为 Observer,更轻量灵活:
// Observer 是一个接受更新数据的函数类型
type Observer func(data interface{})
// Subject 管理观察者并触发通知
type Subject struct {
observers []Observer
mu sync.RWMutex
}
func (s *Subject) Register(obs Observer) {
s.mu.Lock()
defer s.mu.Unlock()
s.observers = append(s.observers, obs)
}
func (s *Subject) Unregister(obs Observer) {
s.mu.Lock()
defer s.mu.Unlock()
for i, o := range s.observers {
if o == obs {
s.observers = append(s.observers[:i], s.observers[i+1:]...)
break
}
}
}
func (s *Subject) Notify(data interface{}) {
s.mu.RLock()
defer s.mu.RUnlock()
for _, obs := range s.observers {
obs(data) // 异步通知?可另起 goroutine,但需注意并发安全
}
}
让业务结构体嵌入 *Subject 或持有其指针,把状态字段的 setter 改为带通知逻辑的方法。
例如实现一个温度传感器:
type TemperatureSensor struct {
*Subject
temperature float64
}
func NewTemperatureSensor() *TemperatureSensor {
return &TemperatureSensor{
Subject: &Subject{observers: make([]Observer, 0)},
}
}
func (t *TemperatureSensor) SetTemperature(temp float64) {
t.temperature = temp
t.Notify(map[string]float64{"temperature": temp})
}
func (t *TemperatureSensor) GetTemperature() float64 {
return t.temperature
}
每个 Observer 函数专注单一响应逻辑,便于测试与复用:
示例注册方式:
sensor := NewTemperatureSensor() // 日志观察者 sensor.Register(func(data interface{}) { fmt.Println("LOG: sensor updated →", data) }) // 告警观察者 sensor.Register(func(data interface{}) { if v, ok := data.(map[string]float64); ok { if t := v["temperature"]; t > 80.0 { fmt.Println("ALERT: High temperature detected!", t) } } }) // 触发变更 sensor.SetTemperature(85.5) // 同时输出 log 和 alert
Go 1.18+ 可用泛型增强类型安全,比如定义 Subject[T];若通知耗时长,可用 channel + goroutine 异步分发;如需支持取消,可结合 context.Context 或返回 func() 取消函数。
简单异步版 Notify 示例:
func (s *Subject) NotifyAsync(data interface{}) {
s.mu.RLock()
obsCopy := append([]Observer(nil), s.observers...) // 安全拷贝
s.mu.RUnlock()
var wg sync.WaitGroup
for _, obs := range obsCopy {
wg.Add(1)
go func(o Observer) {
defer wg.Done()
o(data)
}(obs)
}
wg.Wait()
}
# redis
# go
# golang
# app
# ai
# red
# 封装
# 结构体
# 指针
# 继承
# 接口
# 泛型
# channel
# 对象
# 异步
# 传感器
# ui
# 是一个
# 多个
# 移除
# 进阶
# 推荐使用
# 并可
# 如需
# 发邮件
# 时长
# 复用
相关文章:
公司网站制作需要多少钱,找人做公司网站需要多少钱?
C++用Dijkstra(迪杰斯特拉)算法求最短路径
官网网站制作腾讯审核要多久,联想路由器newifi官网
南京做网站制作公司,南京哈发网络有限公司,公司怎么样,做网页美工DIV+CSS待遇怎么样?
番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?
相册网站制作软件,图片上的网址怎么复制?
如何用AWS免费套餐快速搭建高效网站?
高性能网站服务器配置指南:安全稳定与高效建站核心方案
制作企业网站建设方案,怎样建设一个公司网站?
如何通过智能用户系统一键生成高效建站方案?
如何快速搭建高效服务器建站系统?
小型网站建站如何选择虚拟主机?
建站ABC备案流程中有哪些关键注意事项?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
网站制作企业,网站的banner和导航栏是指什么?
如何在局域网内绑定自建网站域名?
成都网站制作价格表,现在成都广电的单独网络宽带有多少的,资费是什么情况呢?
太平洋网站制作公司,网络用语太平洋是什么意思?
如何通过可视化优化提升建站效果?
娃派WAP自助建站:免费模板+移动优化,快速打造专业网站
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
广东企业建站网站优化与SEO营销核心策略指南
如何在云虚拟主机上快速搭建个人网站?
宁波免费建站如何选择可靠模板与平台?
如何有效防御Web建站篡改攻击?
合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?
微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?
SQL查询语句优化的实用方法总结
简单实现Android验证码
如何快速查询网站的真实建站时间?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
python的本地网站制作,如何创建本地站点?
如何通过IIS搭建网站并配置访问权限?
建站OpenVZ教程与优化策略:配置指南与性能提升
如何在橙子建站上传落地页?操作指南详解
韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
如何解决ASP生成WAP建站中文乱码问题?
网站制作说明怎么写,简述网页设计的流程并说明原因?
如何用5美元大硬盘VPS安全高效搭建个人网站?
建站之星CMS五站合一模板配置与SEO优化指南
香港服务器建站指南:免备案优势与SEO优化技巧全解析
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
香港服务器部署网站为何提示未备案?
常州自助建站:操作简便模板丰富,企业个人快速搭建网站
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
如何用VPS主机快速搭建个人网站?
建站VPS推荐:2025年高性能服务器配置指南
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
如何在阿里云虚拟服务器快速搭建网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。