Go 注册表模式中的异步应答
我正在学习围棋,我想探索一些模式 我想构建一个注册表组件,它维护一些东西的映射,我想提供对它的序列化访问: 现在我的结局是这样的:Go 注册表模式中的异步应答,go,Go,我正在学习围棋,我想探索一些模式 我想构建一个注册表组件,它维护一些东西的映射,我想提供对它的序列化访问: 现在我的结局是这样的: type JobRegistry struct { submission chan JobRegistrySubmitRequest listing chan JobRegistryListRequest } type JobRegistrySubmitRequest struct { request JobSubmissionRequest re
type JobRegistry struct {
submission chan JobRegistrySubmitRequest
listing chan JobRegistryListRequest
}
type JobRegistrySubmitRequest struct {
request JobSubmissionRequest
response chan Job
}
type JobRegistryListRequest struct {
response chan []Job
}
func NewJobRegistry() (this *JobRegistry) {
this = &JobRegistry{make(chan JobRegistrySubmitRequest, 10), make(chan JobRegistryListRequest, 10)}
go func() {
jobMap := make(map[string] Job)
for {
select {
case sub := <- this.submission:
job := MakeJob(sub.request) // ....
jobMap[job.Id] = job
sub.response <- job.Id
case list := <- this.listing:
res := make([]Job, 0, 100)
for _, v := range jobMap {
res = append(res, v)
}
list.response <- res
}
/// case somechannel....
}
}()
return
}
键入JobRegistry结构{
提交chan JobRegistrySubmitRequest
正在列出chan JobRegistryListRequest
}
类型JobRegistrySubmitRequest结构{
请求作业提交请求
回应陈工
}
类型JobRegistryListRequest结构{
回应【】工作
}
func NewJobRegistry()(此*JobRegistry){
this=&JobRegistry{make(chan JobRegistrySubmitRequest,10),make(chan JobRegistryListRequest,10)}
go func(){
jobMap:=make(映射[字符串]作业)
为了{
挑选{
case sub:=我不完全确定我是否理解你,但我会尽量回答你的问题
您需要一个执行发送给它的作业的通用服务。您还可能希望作业可以序列化
我们需要的是一个定义通用作业的接口
type Job interface {
Run()
Serialize(io.Writer)
}
func ReadJob(r io.Reader) {...}
type JobManager struct {
jobs map[int] Job
jobs_c chan Job
}
func NewJobManager (mgr *JobManager) {
mgr := &JobManager{make(map[int]Job),make(chan Job,JOB_QUEUE_SIZE)}
for {
j,ok := <- jobs_c
if !ok {break}
go j.Run()
}
}
type IntJob struct{...}
func (job *IntJob) GetOutChan() chan int {...}
func (job *IntJob) Run() {...}
func (job *IntJob) Serialize(o io.Writer) {...}
类型作业界面{
运行()
序列化(io.Writer)
}
func ReadJob(r io.Reader){…}
类型JobManager结构{
作业映射[int]作业
jobs_c chan Job
}
func新工作经理(经理*工作经理){
经理:=&JobManager{make(映射[int]作业),make(chan作业,作业队列大小)}
为了{
J,OK:=为什么你认为一个错误通道奇怪?这是一个很好的方式来传递错误的通道。你可以用很好的功能来包装它。嗨,Elazar,谢谢你的建议。但是我的场景不仅仅是提交作业,还可以在GOODUTE上接收其他类型的命令,因此选择。ant说manager goroutine是唯一负责访问作业映射的人。我明白,只需使用包装函数隐藏所有内容是可行的,只是想知道是否有一种方法可以在没有这么多样板代码的情况下实现它,因为我正在考虑在其他情况下也使用这种模式。其他命令会是什么样子?您可以使用一个通用的接口{}
通道,并在运行时测试其类型(如果您正在寻找的话)。但是,这不是一个很好的解决方案。请参见此处的示例,是的,这与我感觉到的问题相同:我选择为每个命令使用一个通道(请参阅my JobRegistry结构,它有两个通道,本例中每个操作一个通道)。我在其他语言中使用带有标记类型联合的类型切换模式,在go中,在服务器goroutine中可以,但客户端可以发送任何内容。@ithkull,您必须更改您的设计。请尝试思考命令与执行它们的命令交互的常见方式,并创建一个允许这样做的接口。F或者,如果它们都运行并返回一个值,那么它们都应该遵守接口{run()value}
。
type Job interface {
Run()
Serialize(io.Writer)
}
func ReadJob(r io.Reader) {...}
type JobManager struct {
jobs map[int] Job
jobs_c chan Job
}
func NewJobManager (mgr *JobManager) {
mgr := &JobManager{make(map[int]Job),make(chan Job,JOB_QUEUE_SIZE)}
for {
j,ok := <- jobs_c
if !ok {break}
go j.Run()
}
}
type IntJob struct{...}
func (job *IntJob) GetOutChan() chan int {...}
func (job *IntJob) Run() {...}
func (job *IntJob) Serialize(o io.Writer) {...}
type IntChanWithErr struct {
c chan int
errc chan os.Error
}
func (ch *IntChanWithErr) Next() (v int,err os.Error) {
select {
case v := <- ch.c // not handling closed channel
case err := <- ch.errc
}
return
}