在if语句中进行结构体初始化

huangapple go评论84阅读模式
英文:

Struct initialization in if statements

问题

我想检查一个结构体是否为空,即其所有字段是否都设置为它们的默认值。以下代码可以正常工作:

package main

import "fmt"

type MyStruct struct {
    field1 string
    field2 int
}

func main() {
    var mine MyStruct
    empty := MyStruct{}

    // 检查 mine 是否为空。
    if mine == empty {
        fmt.Print("mine is empty")
    }
}

我想简化一下,所以将空结构体的初始化移到了 if 语句中:

func main() {
    var mine MyStruct

    // 检查 mine 是否为空。
    if mine == MyStruct{} {
        fmt.Print("mine is empty")
    }
}

但是这样不起作用:syntax error: unexpected }, expecting := or = or comma。即使下面的代码看起来几乎和第一个示例相同,也不起作用:

func main() {
    var mine MyStruct

    // 检查 mine 是否为空。
    if empty := MyStruct{}; mine == empty {
        fmt.Print("mine is empty")
    }
}

编译器报错:syntax error: need trailing comma before newline in composite literal。然而,我发现下面的代码可以工作:

func main() {
    var mine MyStruct

    // 检查 mine 是否为空。
    if mine == *new(MyStruct) {
        fmt.Print("mine is empty")
    }
}

有人能解释一下为什么上面两个示例被编译器拒绝吗?顺便问一下:检查一个“空”结构体的惯用方式是什么?最后一个示例可以工作,但对我来说看起来有点奇怪。

英文:

I want to check if a struct is empty, i.e. if all of its fields are set to their default value. The following works as expected:

package main

import "fmt"

type MyStruct struct {
	field1 string
	field2 int
}

func main() {
	var mine MyStruct
	empty := MyStruct{}

	// Check if mine is empty.
	if mine == empty {
		fmt.Print("mine is empty")
	}
}

I wanted to shorten this a bit so I moved the empty struct initialization into the if statement:

func main() {
	var mine MyStruct

	// Check if mine is empty.
	if mine == MyStruct{} {
		fmt.Print("mine is empty")
	}
}

But that does not work: syntax error: unexpected }, expecting := or = or comma. Even the following does not work although it seems almost the same as the first example:

func main() {
	var mine MyStruct

	// Check if mine is empty.
	if empty := MyStruct{}; mine == empty {
		fmt.Print("mine is empty")
	}
}

The compiler says: syntax error: need trailing comma before newline in composite literal. I found the following code to work, however:

func main() {
	var mine MyStruct

	// Check if mine is empty.
	if mine == *new(MyStruct) {
		fmt.Print("mine is empty")
	}
}

Can someone explain why the two above examples are not accepted by the compiler? And while we're at it: What's the idiomatic way to check for an "empty" struct? The last example works but looks a bit odd to me.

答案1

得分: 17

使用括号解决{}的歧义。例如,

package main

import "fmt"

type MyStruct struct {
    field1 string
    field2 int
}

func main() {
    var mine MyStruct

    // 检查 mine 是否为空。
    if mine == (MyStruct{}) {
        fmt.Print("mine is empty")
    }
}

Go编程语言规范

复合字面量

当一个使用TypeName形式的LiteralType的复合字面量出现在关键字和if、for或switch语句的左花括号之间作为操作数时,会出现解析歧义,而且该复合字面量没有被括号、方括号或花括号包围。在这种罕见情况下,字面量的左花括号会被错误地解析为引入语句块的左花括号。为了解决这个歧义,复合字面量必须出现在括号内。

英文:

Resolve the {} ambiguity with parentheses. For example,

package main

import "fmt"

type MyStruct struct {
	field1 string
	field2 int
}

func main() {
	var mine MyStruct

	// Check if mine is empty.
	if mine == (MyStruct{}) {
		fmt.Print("mine is empty")
	}
}

> The Go Programming Language Specification
>
> Composite literals
>
> A parsing ambiguity arises when a composite literal using the TypeName
> form of the LiteralType appears as an operand between the keyword and
> the opening brace of the block of an "if", "for", or "switch"
> statement, and the composite literal is not enclosed in parentheses,
> square brackets, or curly braces. In this rare case, the opening brace
> of the literal is erroneously parsed as the one introducing the block
> of statements. To resolve the ambiguity, the composite literal must
> appear within parentheses.

huangapple
  • 本文由 发表于 2014年8月10日 03:46:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/25222381.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定