gpt4 book ai didi

函数名称前带有下划线的结构标记

转载 作者:IT老高 更新时间:2023-10-28 13:07:59 27 4
gpt4 key购买 nike

我正在使用 go,特别是 QT 绑定(bind)。但是,我不明白在下面的结构中使用前导下划线。我知道一般使用下划线,但不知道这个具体示例。

type CustomLabel struct {
core.QObject

_ func() `constructor:"init"`
_ string `property:"text"`
}

它与结构标签有关吗?

最佳答案

这些被称为空白字段,因为 blank标识符用作字段名称。

它们不能被引用(就像任何以空白标识符作为名称的变量一样),但它们参与结构的内存布局。通常并且实际上它们用作填充,以将后续字段与匹配来自(或去往)另一个系统的数据布局的字节位置(或内存位置)对齐。好处是这些结构值(或者更确切地说是它们的内存空间)可以在一个步骤中简单有效地转储或读取。

@mkopriva 的回答详细说明了该问题的具体用例的用途。

警告:这些空白字段作为“类型注释”应谨慎使用,因为它们会为此类结构的 所有 (!) 值增加不必要的开销.这些字段不能被引用,但它们仍然需要内存。如果您添加一个大小为 8 个字节的空白字段(例如 int64),如果您创建一百万个元素,那么这 8 个字节将计数一百万次。因此,这是对空白字段的“错误”使用:目的是将元信息添加到 type 本身(而不是其实例),但代价是所有元素都需要增加内存.

您可能会说使用大小为 0 的类型,例如 struct{}。更好的是,好像在正确的位置使用(例如,作为第一个字段,推理参见 Struct has different size if the field order is differentWhy position of `[0]byte` in the struct matters? ),它们不会改变结构的大小。尽管如此,使用反射来迭代结构字段的代码仍然必须循环这些字段,因此它会降低此类代码的效率(通常是所有编码/解码过程)。另外,由于现在我们不能使用任意类型,我们失去了携带类型信息的优势。

最后一条语句(关于使用 struct{} 时我们会丢失携带的类型信息)可以被规避。 struct{} 不是唯一大小为 0 的类型,所有长度为 0 的数组的大小也为零(无论实际元素类型如何)。所以我们可以通过使用我们想要合并的类型的 0 大小的数组来保留类型信息,例如:

type CustomLabel struct {
_ [0]func() `constructor:"init"`
_ [0]string `property:"text"`
}

现在这个 CustomLabel 类型在性能方面看起来比所讨论的类型要好得多:它的大小仍然是 0。并且仍然可以使用 Type.Elem 访问数组的元素类型() 就像这个例子:

type CustomLabel struct {
_ [0]func() `constructor:"init"`
_ [0]string `property:"text"`
}

func main() {
f := reflect.ValueOf(CustomLabel{}).Type().Field(0)
fmt.Println(f.Tag)
fmt.Println(f.Type)
fmt.Println(f.Type.Elem())
}

输出(在 Go Playground 上尝试):

constructor:"init"
[0]func()
func()

有关结构标签的概述,请阅读相关问题:What are the use(s) for tags in Go?

关于函数名称前带有下划线的结构标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50387103/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com