Преобразование внутреннего массива структур go в сгенерированный protobuf массив указателей

Я пытаюсь преобразовать внутренний тип в тип, сгенерированный protobuf, и не могу преобразовать массив. Я новичок, поэтому не знаю всех методов, которые могут помочь. Но это моя попытка. При запуске этого кода я получаю

паника: ошибка выполнения: неверный адрес памяти или разыменование нулевого указателя [сигнал SIGSEGV: код нарушения сегментации = 0x1 addr = 0x8 pc = 0x86c724]

наряду с большим количеством других байтовых данных. Мне интересно, как лучше всего преобразовать внутренние структуры в protobufs. Я думаю, что у меня больше всего проблем с кодом, сгенерированным protobuf, который является указателем.

Протоопределения

message GameHistory {
  message Game {
    int64 gameId = 1;
  }

  repeated Game matches = 1;
  string username = 2;
}

message GetRequest {
  string username = 1;
}

message GetGameResponse {
  GameHistory gameHistory = 1;
}

Перейти код

// GameHistory model
type GameHistory struct {
  Game []struct {
    GameID     int64  `json:"gameId"`
  } `json:"games"`
  UserName   string `json:"username"`
}

func constructGameHistoryResponse(gameHistory models.GameHistory) *pb.GetGameResponse {

  games := make([]*pb.GameHistory_Game, len(gameHistory.Games))
  for i := range matchHistory.Matches {
    games[i].GameID = gameHistory.Games[i].GameID
  }

  res := &pb.GetGameResponse{
    GameHistory: &pb.GameHistory{
      Games:    games,
    },
  }
}

person Danny    schedule 27.03.2019    source источник


Ответы (1)


Ваш срез games инициализируется нулевыми значениями, так как он имеет тип []*pb.GameHistory_Game (срез указателей на pb.GameGistory_Game - значение инициализации для указателя равно нулю). Вы хотите получить доступ к свойству GameID этих элементов. Вместо этого вы должны создать их:

for i := range matchHistory.Matches {
    games[i]=&pb.GameHistory{GameID: gameHistory.Games[i].GameID}
}

Кроме того, я рекомендую ознакомиться с документацией по go protobuf, так как у вас есть Marshal и методы Unmarshal для декодирования и кодирования сообщений protobuf .

person Brad    schedule 27.03.2019
comment
Я хотел использовать эти методы, но не могу найти примеры того, как их правильно использовать. Так что, просто для моих знаний, что мне нужно сделать, чтобы установить это значение? - person Danny; 27.03.2019
comment
Если вы больше не хотите получать разыменование нулевого указателя, вы можете начать с установки типа среза в []pb.GameHistory_Game (это GameHistory_Game или GameHistory?) - person Brad; 27.03.2019
comment
для Marshal вам нужен объект типа, сгенерированного путем компиляции ваших protobufs в коде go (с protoc), метод возвращает байтовый срез, в котором хранится сообщение. А для Unmarshal вам нужен байтовый фрагмент, в котором хранится сообщение protbuf, и объект типа, сгенерированного путем компиляции ваших protobuf в коде go (с protoc), например. ошибка: = proto.Unmarshal (protoMessageBytes, objectToStoreDecodedDataInto) - person Brad; 27.03.2019
comment
вы также можете сделать это, чтобы сохранить games в качестве среза указателей и сделать это вместо games[i]=&pb.GameHistory{GameID: gameHistory.Games[i].GameID}. Я думаю, это то, что вы хотите - person Brad; 27.03.2019
comment
Что ж, GameHistory_Game — это объект, сгенерированный с помощью proto, и в GameHistory есть структура Game, которая ему соответствует. Проблема в том, что мои данные сначала поступают в структуру go, а затем в структуру, сгенерированную прототипом. Сначала я посмотрел на преобразование моей структуры Go в срез байтового массива, но не был уверен, что это правильный подход. - person Danny; 27.03.2019
comment
Да, последний комментарий с games[i]=&pb.GameHistory{GameID: gameHistory.Games[i].GameID} был тем, что мне было нужно, спасибо. Я бы хотел, чтобы маршал работал, поэтому я посмотрю на это. Спасибо большое - person Danny; 27.03.2019