Задать вопрос

Google Protobuf — как определить тип пришедшего сообщения?

Изучаю protobuf, столкнулся с такой бедой. Допустим, есть такой .proto:
syntax = "proto3";
package example;
message Kaboom {
    uint64 data = 1;
}
message Oops {
    uint64 data = 1;
}

Сообщения пересылаются по WebSocket между сервером на Golang и клиентом на JavaScript.
Сервер ожидает новых команд от клиента, и клиент может отправить как Kaboom так и Oops. Сервер не может знать наперед, какой тип сообщения придет, и тут возникает вопрос, а как же десериализировать данные, которые пришли через WebSocket не зная типа заранее?
Встречал где-то статью от 2011 года, где на похожий вопрос советовали создать message-обертку, в которую включить существующие типы, а на стороне сервера проверять, какое поле заполнено. Почему-то мне кажется, что это решение далеко от оптимального.
Надеюсь на полезные советы, спасибо что дочитали.
  • Вопрос задан
  • 1658 просмотров
Подписаться 1 Оценить Комментировать
Решения вопроса 1
@SilentFl
вообще говоря можно делать и через message-обертку, но вроде как правильнее делать через Oneof, пример на go можно поизучать тут. выбор типа сообщения - это строки
// Use a type switch to determine which oneof was set.
	switch u := test.Union.(type) {
	case *pb.Test_Number: // u.Number contains the number.
	case *pb.Test_Name: // u.Name contains the string.
	}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
fdhadzh
@fdhadzh
Perfectionist with deadlines
Можно сделать поле `kind`.

syntax = "proto3";

package entity;

message Entity {
  // Kinds:
  //
  // * kaboom
  // * oops
  string kind = 1;

  message Kaboom { uint64 data = 1; }

  message Oops { uint64 data = 1; }

  Kaboom kaboom = 2;

  Oops oops = 3;
}


package main

import (	
	"github.com/golang/protobuf/proto"
	
	"pathtopkg/entity"
)

func main() {
	var e entity.Entity

	err := proto.Unmarshal(buf, &e)
	if err != nil {
		panic(err)
	}

	switch e.Kind {
	case "kaboom":
		// Kaboom
	case "oops":
		// Oops
	default:
		panic("Invalid kind")
	}
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы