指针、泛型、约束、接口和接收器都在扭曲中

问题描述 投票:0回答:1

定义

我的界面

type FirestoreDocument interface {
    GetDocumentKey() string
    SetDocumentKey(key string)
}

实现它的结构

type ImageProcessingJobDocument struct {
    documentKey  string
    Whatever     string    `firestore:"whatever"`
}

func (d *ImageProcessingJobDocument) GetDocumentKey() string {
    return d.documentKey
}

func (d *ImageProcessingJobDocument) SetDocumentKey(key string) {
    d.documentKey = key
}

一些尝试使用上述内容的通用代码。

注意 -

D
实际上是一种返回类型。我不允许将
Execute
Execute[D]
通用,大概 Go 不支持这一点,但我可以将
D
粘贴在下面的结构上,并最终在返回元组
(D, error)
中使用它。

type FirestoreUpdate[T any, D *FirestoreDocument] struct {
    Collection string
    DocumentID string
    Data       T
}

func NewFirestoreUpdate[T any, D *FirestoreDocument]
(collection, documentID string, data T) *FirestoreUpdate[T, D] {
   ...
}

func (u *FirestoreUpdate[T, D]) Execute(ctx context.Context, client *firestore.Client) (D, error) {
    ...
}


使用方法

这是我的使用方法:

    firestoreUpdate := documents.NewFirestoreUpdate[*data.JobProcessingUpdate, 
        data.ImageProcessingJobDocument](documents.CollectionJobs, key, update)

注意 - 请注意,我在这个泛型方法调用中指定了两种类型,第一个是指针,第二个不是。第二份(工作文件)是我们感兴趣的。

问题

当第二种类型不是指针时(参见上面的用法),我得到:

data.ImageProcessingJobDocument does not satisfy *documents.FirestoreDocument (data.ImageProcessingJobDocument missing in *blah/internal/store/documents.FirestoreDocument)

当我指定第二种类型是指针时,我得到:

*data.ImageProcessingJobDocument does not satisfy *documents.FirestoreDocument (*data.ImageProcessingJobDocument missing in *blah/internal/store/documents.FirestoreDocument)

但是当我不指定类型但允许编译器推断它们时,那么

D
最终会被推断为接口
FirestoreDocument

我有 C# 背景,这种事情是可行的。事实上,我可以使

Execute
方法变得通用。

指针是真正令人困惑的,无论是在约束、通用占位符方面(

D
vs.
*D
),但在本例中,关于指针接收器以及这可能如何影响接口是由类型还是由类型实现不是,因此为什么指针和直接值似乎都不满足约束/实现接口。

指针修饰符确实将事物与泛型混淆了。

go generics
1个回答
0
投票

通过定义没有

*
指针的约束,当我开始使用代码时,它似乎允许我选择指向 D 的指针或直接 D。

我之前尝试过这个,但遇到了另一个问题,这导致我尝试指针约束,这导致了SO问题,但我已经解决了另一个问题。

另一个问题只是如何不返回

D
的任何内容,因为目标是在
Execute
的返回元组中定义泛型。

出现错误时,我无法返回

nil, err
,因为 nil 不正确,并且我其他尝试返回“无”的尝试失败了。

无论如何,语法是这样的:

// remove the * to make the constraints all [T any, D FirestoreDocument]
// then return nothing like this;

func (u *FirestoreUpdate[T, D]) Execute(ctx context.Context, client *firestore.Client) (D, error) {
    
    var doc D
    err := doSomething()
    if (err) {
        return doc, fmt.Errorf("whoops: %w", err)
    }
    
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.