Go言語におけるGobエンコーディングとRPCの基礎

Go言語では、データ構造のシリアライズにはGobエンコーディングが利用されます。また、分散システム間通信にはRPC(Remote Procedure Call)が使用されます。

Gobエンコーディングの基本 GobはGo標準ライブラリのencoding/gobパッケージで提供されるバイナリシリアライゼーション形式です。データ構造のエンコードにはEncoder、デコードにはDecoderを使用します。

package main

import (
  "bytes"
  "encoding/gob"
  "fmt"
)

type DataPair struct {
  X, Y, Z int
  Label   string
}

type DecodedPair struct {
  X, Y *int32
  Label string
}

func main() {
  original := DataPair{10, 20, 30, "Example"}
  buffer := serialize(original)
  
  result := deserialize(buffer)
  fmt.Printf("%s: {%d,%d}\n", result.Label, *result.X, *result.Y)
}

func serialize(data interface{}) *bytes.Buffer {
  var buffer bytes.Buffer
  encoder := gob.NewEncoder(&buffer)
  encoder.Encode(data)
  return &buffer
}

func deserialize(data interface{}) *DecodedPair {
  reader := data.(*bytes.Buffer)
  decoder := gob.NewDecoder(reader)
  var q DecodedPair
  decoder.Decode(&q)
  return &q
}

ファイル操作におけるGobの活用 データ構造の永続化にはファイルへのシリアライズが有用です。

package main

import (
  "encoding/gob"
  "fmt"
  "os"
)

type Location struct {
  City    string
  Country string
}

const storagePath = "./location.dat"

func main() {
  saveData()
  restored := loadData()
  fmt.Println(*restored)
}

func saveData() {
  loc := &Location{"Tokyo", "Japan"}
  file, _ := os.Create(storagePath)
  defer file.Close()
  
  encoder := gob.NewEncoder(file)
  encoder.Encode(loc)
}

func loadData() *Location {
  file, _ := os.Open(storagePath)
  defer file.Close()
  
  var loc Location
  decoder := gob.NewDecoder(file)
  decoder.Decode(&loc)
  return &loc
}

RPCの基本実装 Goのnet/rpcパッケージを使用した簡単なRPC実装例を示します。

サーバー実装

package main

import (
  "net"
  "net/http"
  "net/rpc"
)

type Operands struct {
  A, B int
}

type Calculator int

func (c *Calculator) Multiply(args *Operands, result *int) error {
  *result = args.A * args.B
  return nil
}

func main() {
  calc := new(Calculator)
  rpc.Register(calc)
  rpc.HandleHTTP()
  
  listener, _ := net.Listen("tcp", ":8080")
  http.Serve(listener, nil)
}

クライアント実装

package main

import (
  "fmt"
  "net/rpc"
)

type Operands struct {
  A, B int
}

func main() {
  client, _ := rpc.DialHTTP("tcp", "localhost:8080")
  
  params := &Operands{15, 20}
  var response int
  
  client.Call("Calculator.Multiply", params, &response)
  fmt.Printf("Result: %d*%d=%d\n", params.A, params.B, response)
}

RPCメソッドの設計要件

公開メソッド(大文字開始)であること 引数と戻り値の型がエクスポート可能であること 戻り値パラメータはポインタ型であること error型の戻り値を持つこと パラメータ型がGobエンコード可能であること

タグ: Go言語 Gob RPC シリアライゼーション 分散システム

5月14日 00:38 投稿