如何使用Go的类型别名使自己的模型与protobufs一起使用?

I've got some REST API with my models defined as Go structs.

type User struct {
  FirstName string
  LastName  string
}

Then I've got my database methods for getting data.

GetUserByID(id int) (*User, error)

Now I'd like to replace my REST API with https://github.com/twitchtv/twirp .

Therefore I started defining my models inside .proto files.

message User {
  string first_name = 2;
  string last_name = 3;
}

Now I've got two User types. Let's call them the native and the proto type.

I've also got a service defined in my .proto file which returns a user to the frontend.

service Users {
  rpc GetUser(Id) returns (User);
}

This generates an interface that I have to fill in.

func (s *Server) GetUser(context.Context, id) (*User, error) {
  // i'd like to reuse my existing database methods
  u, err := db.GetUserByID(id)
  // handle error
  // do more stuff
  return u, nil
}

Unfortunately this does not work. My database returns a native User but the interface requires a proto user.

Is there an easy way to make it work? Maybe using type aliases?

Thanks a lot!

One way you can solve your problem is by doing the conversion manually.

type User struct {
    FirstName string
    LastName string
}

type protoUser struct {
    firstName string
    lastName string
}

func main() {
    u := db() // Retrieve a user from a mocked db

    fmt.Println("Before:")
    fmt.Printf("%#v
", *u) // What db returns (*protoUser)
    fmt.Println("After:")
    fmt.Printf("%#v
", u.AsUser()) // What conversion returns (User)
}

// Mocked db that returns pointer to protoUser
func db() *protoUser {
    pu := protoUser{"John", "Dough"}
    return &pu
}

// Conversion method (converts protoUser into a User)
func (pu *protoUser) AsUser() User {
    return User{pu.firstName, pu.lastName}
}

The key part is the AsUser method on the protoUser struct.
There we simply write our custom logic for converting a protoUser into a User type we want to be working with.

Working Example