问题描述
我正在尝试实现一个服务器和多个客户端。 客户端会向服务器注册,服务器应该给客户端一个特定的函数来调用。 我不希望特定函数成为另一个 rpc 调用。我正在尝试为 map reduce 制作一个分布式系统,该功能将在客户端进程中执行。
有没有办法在 Go 中传递一个函数作为对远程过程调用的响应? 以下是我尝试过的:
在服务器中:
type ResgisterResponse struct {
Ack bool
MapFunc func()
}
func (a *API) RegisterWorker(addr string,reply *ResgisterResponse) error {
a.worker[addr] = "idle" //idle,working,complete
fmt.Printf("Wokers : %+v\n",a.worker)
*reply = ResgisterResponse{
Ack: true,MapFunc: func() {
fmt.Println("Hello Worker")
},}
return nil
}
在客户端:
var reply struct {
Ack bool
MapFunc func()
}
err = client.Call("API.RegisterWorker",getLocalAddr()+":"+localPort,&reply)
must(err)
fmt.Println("Worker registered")
reply.MapFunc()
这个课程我得到了 nil 指针错误。
panic: runtime error: invalid memory address or nil pointer dereference
解决方法
由于语言设计的原因,无法通过网络发送普通函数。在单个程序中,您可以将函数作为参数传递,因为它们是在同一个二进制文件中编译的。在服务器进程中,您可以获取它们的地址/引用,因为它们被映射到内存中,但是当您发送函数时,您实际上发送了指向它的指针,该指针不是客户端内存中的有效地址(因此会出现无效指针错误)。>
为了解决您的问题,我会让客户端根据 id(可能是提及函数名称的字符串)向服务器注册一组可用函数。服务器将在 Run RPC 调用中发回函数 id,客户端将根据此 id 选择函数并运行它
还有一些实验性库可以在运行时评估 Go 代码,但我认为它们不安全。 This 就是一个例子。