redisのブロードキャストで構造体データを運ぶ時の注意(というか、golangのキャストがC/C++みたいに単純でない件)
以前、こちらで、redisのブロードキャスト(Pub/Sub)の方法について2つほど紹介しましたが、試した結果、こっちの方が安定して調子が良くて、現在、こちら(redigo)を使っています
Redigoを使う(6) パブリッシュ/サブスクライブ
で紹介されていた、サンプルプログラムを使って、構造体のデータを丸ごと送信しようとしたのですが、Golangの厳しい型チェックに掴まって、なかなか上手く動かすことができません。
ただ、構造体をJSON形式にすれば、成功することは分かっています。
しかし、今の段階で構造体をJSONに変更すると、その影響が、プログラム全体に波及し、作業が膨大になるので、これはしたくありませんでした。
もしかしたら、構造体のブロードキャストも、JSONの時と同じように、"json.Unmarshal"、 "json.Marshal" を使えばいけるかな? と思ってやってみたら、あっさりと成功しました。
上記の記事のサンプルプログラムを、構造体データ送付用に改造したものを開示しておきます。
■パブリッシャ(発行元)側
// go run pub.go
// goga\1-9-6\others\pub.go
package main
import (
"encoding/json"
"fmt"
"github.com/gomodule/redigo/redis"
)
type Ch5_info struct {
Bus_num int // バスの番号
CC int // 1: 座標情報 2: 停車位置情報
Present int // 停車位置番号
Lat float64 //
Lon float64 //
}
func main() {
// 接続
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
panic(err)
}
defer conn.Close()
c5i := new(Ch5_info)
c5i.Bus_num = 1
c5i.CC = 2
c5i.Present = 23
c5i.Lat = 12.34
c5i.Lon = 56.78
json_c5i, _ := json.Marshal(c5i)
// パブリッシュ
r, err := redis.Int(conn.Do("PUBLISH", "channel_1", json_c5i))
if err != nil {
panic(err)
}
fmt.Println(r)
}
■サブスクライブ(購読者)側
// go run sub.go
// goga\1-9-6\others\sub.go
package main
import (
"encoding/json"
"fmt"
"github.com/gomodule/redigo/redis"
)
type Ch5_info struct {
Bus_num int // バスの番号
CC int // 1: 座標情報 2: 停車位置情報
Present int // 停車位置番号
Lat float64 //
Lon float64 //
}
func main() {
// 接続
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
panic(err)
}
defer conn.Close()
psc := redis.PubSubConn{Conn: conn}
psc.Subscribe("channel_1", "channel_2", "channel_3")
for {
switch v := psc.Receive().(type) {
case redis.Message:
fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
c5i := new(Ch5_info)
_ = json.Unmarshal(v.Data, &c5i)
// 試しに2つほど出力してみる
fmt.Println(c5i.Bus_num)
fmt.Println(c5i.Lon)
case redis.Subscription:
fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
case error:
return
}
}
}
私のような悩み持っている人、世界中に沢山いました。
Golangは、C/C++みたいに、自己責任で自由にキャストできないんですよね。
memset()を使って、大量の配列の変数を一気に変更させてしまう、ということもできないようで、Golang不便だなぁ、って思います。