我正在寻找订阅 Go 中属性更改的解决方案。鉴于以下结构,我想实现一个订阅其源属性的派生属性,并且只有在被读取时它才会重新评估自身。如果一个或多个来源发生了变化,它会因为收到通知或通过检查“脏标志”(频道?)而知道这样做。 编辑:我不是在寻找一个“getter”函数,它不会缓存获取的值,而是在每次读取时都对它们进行 fethcing)。另请参阅下面添加的 DeriveAndSubscribe 方法,说明派生的 FullName 会做什么)。
我想这类似于一个相当典型的案例。请参阅下面的示例:
type Person struct {
/FullName string // Derived, from the two below:
FirstName string // persistent
LastName string // persistent
}
对于远订阅/获取,该概念也必须是“可见的”,例如从底层 Person 对象派生其详细用户信息的 User 对象:
type User struct {
person *Person
/FullName string // Derived from person.FullName above
}
(好吧,人们的名字不会经常改变,但例子一定很简单)。
我自己对此的第一个想法是,
拉- 派生属性(全名)是“懒惰的”(仅在有人阅读它/它们时评估)。因此,仅在评估 Fullname 字符串时“拉”任何订阅(“脏”标志/通知)似乎是最自然的,即“询问”是否发生了任何更改。
缓存- 派生值后,将其存储在(隐藏)字段 (_fullName) 中,以便在下一次读取时重复使用该字符串,前提是其订阅值未更改。
延迟订阅——当有人读取 FullName 属性时,不仅派生操作应该是“延迟的”,而且订阅本身也应该仅在第一次评估时放置(当有人读取属性时)。
使用 pull而不是 push 的充分理由似乎是,当底层属性发生变化时,订阅属性可能存在也可能不存在。如果源处没有“发送列表”,那么如果/当最终订阅属性/对象消失时,就不需要“取消注册”。并进一步; 在分布式场景(不同机器上的用户和人员)中,最好仅在实际明确要求数据时才更新内容(订阅也适用,只能在第一次读取 FullName 时放置)。
如果一个 goroutine(可选)可以在 CPU 不是很忙时更新(重新评估)FullName 属性,那么奢侈将是,而如果有人读取 FullName 属性,则将立即强制执行重新评估(两者都可以在一个解决方案中实现?) .
无论如何,这里是需要放置的订阅(ASCII 模型):
[Person]./FullName --> [Person].FirstName // Subscribe 1
[Person].LastName // Subscribe 2
和
[User]./FullName --> [User].person./FullName // Subscribe 3
也就是说,共有三 (3) 个下标来保持 User.FullName 属性更新。(暂时忽略 [User].person-link)。可以使用渠道来实现这样的事情吗?如果可以,嗯……如何?
在上面插入隐藏字段的结构下方(用于缓存派生结果,直到下次源属性变得“脏”):
type Person struct {
/FullName string // Derived
_fullName string // "cache"
FirstName string
LastName string
}
和:
type User struct {
person *Person
/FullName string // Derived
_fullName string // "cache"
}
编辑: Person-FullName-attribute 可以通过这样的方法提供服务(它可以稍后打包到类型化的属性对象(结构)中):
func (p *Person) _FullName_DeriveAndSubscribe(Subscriber chan) string {
if /* check if channel(s) is "dirty" */ {
//
// Keep an internal channel, and get hold of the channel, or
// Chan of Chan(?) wich can notify us if any underlaying values change:
//
// _subscr = Subscriber
//
// Now, update the cache
_fullName = FirstName + " " + LastName
}
return _fullName // return the cached value
}