I'm learning microservices with Node and Go.
I'm now having a problem at querying all users from database (postgres) with Gorm.
I usually query like this to get all users and it works:
    // Fetch connection and close db
    db := InitPg()
    defer db.Close()
    // Create an array of users to populate
    var users []*User
    db.Find(&users)
    // Successfully returns an array of users
    return users, nil
But now with generated protobuf, it complains:
func (s *Server) Index(ctx context.Context, _ *shop.Empty) (*shop.IndexUserResponse, error) {
    // func (s *Server) Index(ctx context.Context, request *shop.Empty) error {
    db := InitPg()
    defer db.Close()
    // Confirmed created 2 users in database
    var users []*User
    if err := db.Find(&users).Error; err != nil {
        panic(err)
    }
    // Log prints these:
    // 2020/01/04 20:13:47 [0xc0001da6c0 0xc0001da7e0]
    // 2020/01/04 20:13:51 [0xc0001dade0 0xc0001daf00]
    log.Print(users)
    // It complains right here ------------ v
    return &shop.IndexUserResponse{Users: users}, nil
}
[compiler] [E] cannot use users (variable of type []*User) as []*genproto.User value in struct literal
This is user model file:
type User struct {
    gorm.Model
    Email    string `json:"email" gorm:"type:varchar(100);unique_index" validate:"required,email"`
    Password string `json:"password" validate:"required,gte=10"`
}
Here's my proto file:
syntax = "proto3";
package shop;
service UserService {
  rpc Index(Empty) returns (IndexUserResponse) {}
}
message Empty {}
message User {
  int32 id = 1;
  string email = 2;
}
message IndexUserResponse {
  repeated User users = 1;
}
And this is from go generated proto file:
// shop.pb.go
type IndexUserResponse struct {
    Users                []*User  `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}
type User struct {
    Id                   int32    `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
    Email                string   `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}
How can I query and return an array users?
Edit 2:
Tried as @reda suggested, convert the []*User slice to []*genproto.User:
package main
import (
    "context"
    shop "gitlab.com/me/shop/service/user/genproto"
)
func (s *Server) Index(ctx context.Context, _ *shop.Empty) (*shop.IndexUserResponse, error) {
    db := InitPg()
    defer db.Close()
    var users []*User
    if err := db.Find(&users).Error; err != nil {
        panic(err)
    }
    pUsers := make([]*shop.User, len(users))
    for _, u := range users {
        pUsers = append(pUsers,
            &shop.User{
                Id:    int32(u.ID),
                Email: u.Email,
            })
    }
    return &shop.IndexUserResponse{Users: pUsers}, nil
}
This time got:
ERROR: 2020/01/05 10:55:43 grpc: server failed to encode response:  rpc error: code = Internal desc = grpc: error while marshaling: proto: repeated field Users has nil element.
Log prints: 2020/01/05 10:56:04 [<nil> id:1 email:"[email protected]" ]
You need to manually convert the []*User slice to []*genproto.User one. Golang can't let you do the cast
...
pUsers := make([]*genproto.User, 0)
for _, u := range users {
  pUsers = append(pUsers, &genproto.User{ID: u.ID, Email: u.Email})
}
return &shop.IndexUserResponse{Users: pUsers}, nil
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With