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