Return Gorm 中的数组

Return an array in Go with Gorm

我正在使用 Node 和 Go 学习微服务。

我现在在使用 Gorm 从数据库 (postgres) 查询所有用户时遇到问题。

我通常这样查询以获取所有用户并且有效:

    // 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

但是现在使用生成的 protobuf,它会抱怨:

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

这是用户模型文件:

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"`
}

这是我的原型文件:

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;
}

这是从 go 生成的原型文件:

// 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:"-"`
}

如何查询和 return 数组用户?


编辑 2:

按照@reda 的建议尝试,将 []*User 切片转换为 []*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
}

本次获得:

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.

日志打印:2020/01/05 10:56:04 [<nil> id:1 email:"some@one.com" ]

您需要手动将 []*User 切片转换为 []*genproto.User 切片。 Golang 不能让你做演员

...

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