英文:
what means two curly brackets in a row in structure 'struct' in Go lang?
问题
我在使用Golang的map时遇到了一种奇怪的形式。我用关键词"使用结构体时使用两个花括号"进行了搜索,但没有找到相关信息。在下面的代码中,"struct{}{}"的意思是什么?
menu := map[string]interface{}{
"icecream": "delicious",
"eggs": struct {
price float64
}{"chicken", 1.75}
}
英文:
I'm facing with kind of strange shape when I'm using map in Golang. I searched about it with keywords "using two curly brackets when using struct" but couldn't find. What does it mean using like below 'struct{}{}'?
menu := map[string]interface{}{
"icecream": "delicious",
"eggs":struct {
price float64
}{"chicken", 1.75} }
答案1
得分: 1
让我们来分解一下:
menu := map[string]interface{}{
创建一个名为menu
的变量,类型为map[string]interface{}
(interface{}
表示实现了一个没有方法的接口的任何类型,因此基本上可以分配任何类型)。最后一个开括号是实际数据写在其中的地方,所以:
foo := map[string]int{}
foo["bar"] = 1
可以写成
foo := map[string]int{
"bar": 1,
}
现在在你的代码中,第一个键值对很简单:
"icecream": "delicious",
第二个键值对是你不清楚的部分:
"eggs":struct {
price float64
}{"chicken", 1.75} }
现在这段代码无法编译,但让我们将其改为可以编译的形式:
"eggs":struct {
kind string
price float64
}{"chicken", 1.75} }
我们在这里做的是向menu
映射(类型为map[string]any
)添加一个键,而键eggs
的值是一个结构体。具体来说,是一个带有2个字段的匿名结构体:
struct {
kind string
price float74
}
我们想要设置字段的特定值,所以我们必须初始化这个结构体:
struct {
kind string
price float64
}{"chicken", 1.75}
这与写成以下形式是相同的:
eggs := struct{
kind string
price float64
}{
kind: "chicken",
price: 1.75,
}
甚至可以这样写:
type Egg struct {
kind string
price float64
}
menu := map[string]any{
"icecream": "delicious",
"eggs": Egg{
kind: "chicken",
price: 1.75,
},
}
在这里可能让你困惑的是在初始化结构体时省略了字段(这被认为是不好的形式,只有在字段的顺序被保留时才能正常工作)。假设像这样:
menu := map[string]any{
"icecream": "delicious",
"eggs": struct{
kind string
price float64
}{
kind: "chicken",
price: 1.75,
},
}
那么以下代码将无法工作:
menu := map[string]any{
"icecream": "delicious",
"eggs": struct{
kind string
price float64
}{
1.75, // 结构体的第一个字段应为字符串
},
}
但这样可以:
menu := map[string]any{
"icecream": "delicious",
"eggs": struct{
kind string
price float64
}{
price: 1.75,
},
}
总的来说,在测试中或用于(解)编组大型数据集的类型之外,很少见到这种情况。我认为我上次在代码中使用这种匿名结构体的时间是当我需要接收和传递XML数据块时,但不对其进行任何处理,我会创建类似于以下的类型:
type XMLInput struct {
// 我实际需要使用的数据字段
Details struct {
// 需要确保设置的字段,但不进行任何处理,因此不需要可用的类型
} `xml:"whatever_tag"`
}
英文:
So let's break this down:
menu := map[string]interface{}{
Creates a variable called menu
, of type map[string]interface{}
(interface{}
being any type that implements an interface with zero methods, so basically any type can be assigned). The last opening bracket is where the actual data contained within this map can be written, so:
foo := map[string]int{}
foo["bar"] = 1
Can be written as
foo := map[string]int{
"bar": 1,
}
Now in your code, the first key-value pair is simple:
"icecream": "delicious",
The second one is the one you're unclear about:
"eggs":struct {
price float64
}{"chicken", 1.75} }
Now this code is not going to compile, but let's change it to something that will:
"eggs":struct {
kind string
price float64
}{"chicken", 1.75} }
What we're doing here is adding a key to the meny
map (type map[string]any
), and the value assigned to the key eggs
is a struct. Specifically an anonymous struct with 2 fields:
struct {
kind string
price float74
}
We want to set the fields to certain values, so we have to initialise this struct:
struct {
kind string
price float64
}{"chicken", 1.75}
This is the same as writing:
eggs := struct{
kind string
price float64
}{
kind: "chicken",
price: 1.75,
}
Or even:
type Egg struct {
kind string
price float64
}
menu := map[string]any{
"icecream": "delicious",
"eggs": Egg{
kind: "chicken",
price: 1.75,
},
}
The thing that probably threw you off here is the omission of the fields when initialising the struct (which is considered bad form, and only really works if the order of the fields is preserved. Assuming something like this:
menu := map[string]any{
"icecream": "delicious",
"eggs": struct{
kind string
price float64
}{
kind: "chicken",
price: 1.75,
},
}
Then the following code won't work:
menu := map[string]any{
"icecream": "delicious",
"eggs": struct{
kind string
price float64
}{
1.75, // first field in struct is expected to be a string
},
}
But this will:
menu := map[string]any{
"icecream": "delicious",
"eggs": struct{
kind string
price float64
}{
price: 1.75,
},
}
Overall, it's not that common to see things like this outside of tests, or types that are used to (un) marshal large data-sets where you don't need to use/separate subsets of the data. I think the last time I've used this kind of anonymous structs in code was when I had to receive and pass on chunks of XML data, but do no processing on it, I would create types like:
type XMLInput struct {
// fields of data I actually needed to use
Details struct {
// fields that I needed to make sure were set, but didn't do any processing on, so I didn't need a usable type
} `xml:"whatever_tag"`
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论