0

In my gRPC service, which was written in golang , I have such rpc method called CreateCity. As you can see, in this method, I want to create a new record in the database and return all the information about this record as a response.

func (server *Server) CreateCity(context context.Context, request *proto.CreateCityRequest) (*proto.CreateCityResponse, error) {
    city := proto.City {
        Name: request.GetCity().Name,
        Country: request.GetCity().Country,
    }

    err := databases.DBGORM.Table("city").Create(&city).Error
    if err != nil {
        utils.Logger().Println(err.Error())
        return nil, status.Errorf(codes.Internal, err.Error())
    }

    result := &proto.CreateCityResponse {
        City: &city,
    }

    return result, nil
}

proto file looks like this:

syntax = "proto3";

package proto;

import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";

option go_package = "./proto";

service CityService {
    rpc CreateCity(CreateCityRequest) returns (CreateCityResponse) {}
}

message City {
    google.protobuf.StringValue name = 1 [json_name = "name", (gogoproto.jsontag) = "name", (gogoproto.wktpointer) = true];
    google.protobuf.StringValue country = 2 [json_name = "country", (gogoproto.jsontag) = "country", (gogoproto.wktpointer) = true];
}

message CreateDealerGroupRequest {
    City city = 1;
}

message CreateDealerGroupResponse {
    City city = 1;
}

Is it possible to dynamically fill in the struct with data without explicitly specifying the name? As you can see now, I explicitly specify the name of the fields and their value:

city := proto.City {
    Name: request.GetCity().Name,
    Country: request.GetCity().Country,
}
Nurzhan Nogerbek
  • 4,806
  • 16
  • 87
  • 193
  • Does this answer your question? [Copy one struct to another where structs have same members and different types](https://stackoverflow.com/questions/37246473/copy-one-struct-to-another-where-structs-have-same-members-and-different-types) – Eklavya May 17 '20 at 09:11

2 Answers2

0

You can use json.Marshal create json byte array and then json.Unmarshal

inrec, _ := json.Marshal(request.GetCity())
json.Unmarshal(inrec, &city)
Kmarlon Pereira
  • 59
  • 2
  • 10
0

I believe your best bet to do what you want is to use reflection and go through all the fields of the source struct, compare them to the target struct and assign them if they match.

A quick google search turned up this package: https://github.com/stroiman/go-automapper. (I haven't used it myself, just putting it here as an example)
The code you'd want is here: here.
Don't want to include the code in this answer since you might want to change it - but the general idea is there.

Personally, I'd go with the manual approach (as you do now) if at all feasible. Relying on reflection will be slower, but maybe more importantly changes to the the model might affect the mapping in unforseen ways. Just depends on your use case imo.

erikbozic
  • 1,605
  • 1
  • 16
  • 21