是否可以发送函数作为 RPC 的响应

问题描述

我正在尝试实现一个服务器和多个客户端。 客户端会向服务器注册,服务器应该给客户端一个特定的函数调用。 我不希望特定函数成为另一个 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 就是一个例子。