复合字面量使用未命名字段

89

我正在使用新的官方mongodb驱动程序开发golang。我创建了一个复杂的查询,将数据插入到mongo db中,然后根据一个元素值对其进行排序。我正在使用过滤器,在其中使用bson类型创建:

filter := bson.D{{"autorefid", "100"}}

但是它显示了一个警告:

primitive.E 组合字面量使用未键控字段

这些警告在我的代码中制造了一团糟。


这段代码看起来没问题。也许错误在另一行? - Sergio Tulentsev
@SergioTulentsev,这不是错误,而是go vet正在显示的警告。 - Himanshu
好的,谢谢你发布自我回答,今天学到了新东西 :) - Sergio Tulentsev
1
要在 VS Code 中禁用警告,请按 Ctrl+, 搜索 go.vetflags 并添加 -composites=false - PeterM
6个回答

98

通过将检查标志设置为false,可以停止警告。

$ go doc cmd/vet
默认情况下将执行所有检查。如果某些标志被明确设置为 true,则只运行这些测试。相反,如果任何标志被明确设置为 false,则仅禁用这些测试。因此,“-printf=true” 运行 printf 检查,“-printf=false” 运行除 printf 检查之外的所有检查。
Unkeyed composite literals

Flag: -composites

Composite struct literals that do not use the field-keyed syntax.

然而,警告是由于在设置primitive.E结构体的值时未提供键名。

primitive.E结构体设置键名将消除警告消息。例如:

filter := bson.D{primitive.E{Key: "autorefid", Value: "100"}}

primitive 包含了一些与 Go 原始类型类似的类型,用于表示在 BSON 中没有直接对应的 Go 原始类型。

type E struct {
    Key   string
    Value interface{}
}

E代表D的BSON元素。通常在D内使用。

更多信息请参见primitive.E


当我们提供键时,我认为代码更加清晰。 - Karl Anthony Baluyot
8
筛选器 := bson.D{{Key: "autorefid", Value: "100"}} // 跳过 primitive.E 也可以工作。 - Chris W
1
如果我们将其存储在变量e := functionWhichReturnsE(...)中,并且我们需要一个bson.D,我们需要执行bd := bson.D{Key: e.Key, Value: e.Value}?看起来不错,直到你对template.Template这样做。最好禁用它。 - Phani Rithvij
我想我会在我的 utils 包中添加类似于 func E(s string, i interface{}) bson.E { return bson.E{ Key: s, Value: i, } } 的东西 :S - Cirelli94

41

鉴于没有其他人指出这一点,这个警告是为了保护您免受第三方API更改而导致的代码静默破坏。

忽略此vet警告可能会导致非常严重且难以跟踪的运行时错误,因此最好始终明确指定第三方struct的键

如果您使用的库的维护者决定由于任何原因更改其struct中的元素顺序,就会发生这种情况。例如,在OP案例中将KeyValue交换。您的代码仍然可以正常编译,但您想要的键现在将作为值传递,反之亦然,并且事情只会以意想不到的方式开始崩溃。


6
这就解释了为什么它只会警告来自其他包的结构体,而不会警告来自代码同一包中的结构体。 - fefe
大多数代码使用相同的模型包来进行结构体处理。这不应该是一个警告,因为使用结构体字面初始化可以捕获复制结构体时的错误。在结构体中新增的字段将在编译时失败。如果我们使用键值类型的初始化,我们将无法在复制操作期间捕获缺少的新字段。 - user640554
奇怪的是,如果你查看Mongo的Golang文档和Compass的导出代码功能,它们并没有使用键值对来表示bson.D。 - Someone Special

40

您可以简单地更改:

filter := bson.D{{"autorefid", "100"}}

致:

filter := bson.D{{Key: "autorefid", Value: "100"}}

//根据Chris W所说,跳过primitive.E


26

您可以更改:

filter := bson.D{{"autorefid", "100"}}

至:

filter := bson.D{primitive.E{Key: "autorefid", Value: "100"}}

13

实际上,如果一个BSON文档的有序表示形式并非必需,您可以通过简单更改将其转换为无序表示形式。

filter := bson.D{{"autorefid", "100"}}

filter := bson.M{"autorefid": "100"}

请查看这篇stackoverflow答案,了解有关bson.Dbson.M的更多细节。 MongoDB服务器足够聪明,可以找到匹配的索引,无论使用的顺序如何。


2
如果您正在使用 vscode,请在设置中禁用以下内容:

输入图像描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接