英文:
How to make gqlgen dataloader Loader.Load(key) return a function that returns an explicit data type instead of interface{}?
问题
我想使用graph-gophers/dataloader
来实现一个用于批量获取用户的数据加载器。
我已经按照以下方式实现了它,但是我需要返回一个明确的数据类型,而不是interface{}
。
首先,我使用给定的dataloader.Keys
通过函数GetUsers
创建了UserReader
:
type UserReader struct {
userCtrl user.Controller // 这是我的用户服务,用于创建、获取和删除用户
}
func newUserReader(userCtrl user.Controller) UserReader {
return UserReader{
userCtrl: userCtrl,
}
}
// GetUsers根据给定的键返回结果列表
func (reader UserReader) GetUsers(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
output := make([]*dataloader.Result, len(keys))
for i, key := range keys {
userID := key.String()
// 根据字符串userID获取用户列表
result, err := reader.userCtrl.GetUsers(ctx, userID)
output[i] = &dataloader.Result{Data: result, Error: err}
}
return output
}
然后,我使用函数GetUser
创建了一个Loader
,通过userID
获取一个用户,它不会在单个请求中多次请求userCtrl
的数据。
type Loader struct {
userLoader *dataloader.Loader
}
func newLoader(userCtrl user.Controller) Loader {
userReader := newUserReader(userCtrl)
return Loader{
// 使用批处理函数创建新的用户加载器
userLoader: dataloader.NewBatchedLoader(userReader.GetUsers),
}
}
// UserLoader返回用户加载器
func (loader Loader) UserLoader() *dataloader.Loader {
return loader.userLoader
}
// GetUser根据给定的参数返回一个用户
func (loader impl) GetUser(ctx context.Context, userID string) (model.User, error) {
// FromCtx从上下文中获取加载器(如果存在),否则返回nil。
ctxLoader := FromCtx(ctx)
// Thunk是带有interface{}类型和错误的函数返回值
thunk := ctxLoader.UserLoader().Load(ctx, dataloader.StringKey(userID))
result, err := thunk()
if err != nil {
return nil, err
}
return result.(model.User), nil // 在这里转换数据类型!!!
}
最后,可以这样使用:
dataloader.FromCtx(ctx).GetUser(ctx, userID)
但是我希望userReader.getUsers
返回一个包含model.user
的对象,而不是interface{}
,因为我不想在Loader.getUser
函数中进行数据类型转换。
有没有办法让dataloader.Result
返回特定的数据类型,而不是interface{}
?
英文:
I want to use graph-gophers/dataloader
to implement a dataloader for bulk-fetching users.
I have implemented it like below but I need to return an explicit data type, not an interface{}
Firstly, I create UserReader
with function GetUsers
by given dataloader.Keys
:
type UserReader struct {
userCtrl user.Controller // This is my user service for Create, Get, Delete user
}
func newUserReader(userCtrl user.Controller) UserReader {
return UserReader{
userCtrl: userCtrl,
}
}
// GetUsers return a list of result by given keys
func (reader UserReader) GetUsers(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
output := make([]*dataloader.Result, len(keys))
for i, key := range keys {
userID := key.String()
// Get list of user by string userID
result, err := reader.userCtrl.GetUsers(ctx, userID)
output[i] = &dataloader.Result{Data: result, Error: err}
}
return output
}
And then, I create a Loader
with function GetUser
to get a user by userID
, it won't request data from userCtrl
more than 1 time in a single request.
type Loader struct {
userLoader *dataloader.Loader
}
func newLoader(userCtrl user.Controller) Loader {
userReader := newUserReader(userCtrl)
return Loader{
// Create new user loader with batch function
userLoader: dataloader.NewBatchedLoader(userReader.GetUsers),
}
}
// UserLoader returns the user loader
func (loader Loader) UserLoader() *dataloader.Loader {
return loader.userLoader
}
// GetUser return a user by given parameter
func (loader impl) GetUser(ctx context.Context, userID string) (model.User, error) {
// FromCtx gets a Loader from context if it exists, else nil.
ctxLoader := FromCtx(ctx)
// Thunk is function return value with interface{} type and error
thunk := ctxLoader.UserLoader().Load(ctx, dataloader.StringKey(userID))
result, err := thunk()
if err != nil {
return nil, err
}
return result.(model.User), nil // Convert datatype here!!!
}
And finally, It can be use
dataloader.FromCtx(ctx).GetUser(ctx, userID)
But I need userReader.getUsers
to return an object containing model.user
not interface{}
because I don't want to convert the data type in the Loader.getUser
function.
Is there a way to have dataloader.Result
return a certain data type instead of the interface{}
?
答案1
得分: 2
graph-gophers/dataloader
的v7
版本支持泛型。具体来说,BatchFunc
签名已经改变,因此您可以指定结果类型。
英文:
The v7
version of graph-gophers/dataloader
supports generics. Specifically, the BatchFunc
signature has changed so you can specify the resulting type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论