関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。
Goの net はとても便利ですが、 たまに、パパっと通信処理を書いてしまいたいときがあります。
通信メッセージ設計とかも面倒臭い、つまり、RPC通信でパパっと呼び出したいってときです。gRPCを使えば良いってなるのですが、いちいちインストールしたりして用意するのも面倒。
どうせ、Go同士の通信なので言語非依存性とかも要らない。
とかいうときに、net/rpc さんが便利です。内部のエンコードには encoding/gob が利用されているため、Goアプリ専用のRPC通信となりますが、サクッと作れます。
サンプル
main.go
サンプルなので、サーバとクライアント兼用です。
package main import ( "flag" "fmt" "net" "net/rpc" ) type ( Args struct { IsServer bool X int64 Y int64 } RpcArgs struct { X int64 Y int64 } RpcReply struct { Result int64 } Service struct{} ) func (me *Service) Multiply(req *RpcArgs, res *RpcReply) error { if req == nil { return fmt.Errorf("req is nil") } result := req.X * req.Y res.Result = result return nil } var ( args Args ) func init() { flag.BoolVar(&args.IsServer, "server", false, "server mode") flag.Int64Var(&args.X, "x", 0, "X") flag.Int64Var(&args.Y, "y", 0, "Y") } func main() { flag.Parse() if err := run(); err != nil { panic(err) } } func run() error { var err error switch args.IsServer { case true: err = runServer() default: err = runClient() } if err != nil { return err } return nil } func runServer() error { // // RPCとして公開するサービス登録 // service := new(Service) rpc.Register(service) l, err := net.Listen("tcp", ":8888") if err != nil { return err } defer l.Close() rpc.Accept(l) // rpc.Accept(net.Listener) は以下と同じ。 // // for { // conn, err := l.Accept() // if err != nil { // return err // } // go rpc.ServeConn(conn) // } return nil } func runClient() error { client, err := rpc.Dial("tcp", ":8888") if err != nil { return err } defer client.Close() // // RPC 呼び出し // サービスメソッドの引数は arg, reply ともにポインタで渡すこと // const ( serviceMethod = "Service.Multiply" ) var ( a = RpcArgs{X: args.X, Y: args.Y} r RpcReply ) err = client.Call(serviceMethod, &a, &r) if err != nil { return err } fmt.Printf("%d * %d = %d\n", args.X, args.Y, r.Result) return nil }
Taskfile.yml
# https://taskfile.dev version: "3" tasks: default: cmds: - task: build - task: run build: cmds: - go build -o app . run: cmds: - ./app -server & - sleep 1 - ./app -x 2071723 -y 5363222357 - sleep 1 - pkill app watch: cmds: - cmd: sudo tcpdump -i lo -n 'tcp port 8888' -S -X interactive: true
shell
実行すると以下のように出力されます。
$ task task: [run] ./app -server & task: [run] sleep 1 task: [run] ./app -x 2071723 -y 5363222357 2071723 * 5363222357 = 11111111111111111 task: [run] sleep 1 task: [run] pkill app
参考情報
https://github.com/devlights/try-golang-extlib/tree/main/examples/socket/tcp_rpcgithub.com
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。





