Go 程序之间可以使用 net/rpc 包实现相互通信,这是另一种客户端-服务器应用场景。它提供了一种方便的途径,通过网络连接调用远程函数。当然,仅当程序运行在不同机器上时,这项技术才实用。rpc 包建立在 gob 包之上,实现了自动编码/解码传输的跨网络方法调用。
服务器端需要注册一个对象实例,与其类型名一起,使之成为一项可见的服务:它允许远程客户端跨越网络或其他 I/O 连接访问此对象已导出的方法。总之就是在网络上暴露类型的方法。
rpc 包使用了 http 和 tcp 协议,以及用于数据传输的 gob 包。服务器端可以注册多个不同类型的对象(服务),但同一类型的多个对象会产生错误。
小结:
func (t *T) MethodName(argType T1, replyType *T2) error
T1 和 T2 必须能被 encoding/gob 包编码和解码
服务端:
package main
import (
"fmt"
"log"
"net"
"net/rpc"
)
type HelloService struct{}
func (p *HelloService) Hello(request string, reply *string) error {
*reply = "hello: " + request
fmt.Println("hello方法被调用,返回给客户端的结果为: ", *reply)
return nil
}
func main() {
rpc.RegisterName("HelloService", new(HelloService))
listener, err := net.Listen("tcp", ":5200")
if err != nil {
log.Fatal(err)
}
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
rpc.ServeConn(conn)
}
客户端:
package main
import (
"fmt"
"log"
"net/rpc"
)
func main() {
client, err := rpc.Dial("tcp", "localhost:5200")
if err != nil {
log.Fatal(err)
}
var reply string
err = client.Call("HelloService.Hello", "chloe", &reply)
if err != nil {
log.Fatal(err)
}
fmt.Println("远程调用,响应结果为: " + reply)
}