Struct 无法在Go中的if构造中初始化结构

Struct 无法在Go中的if构造中初始化结构,struct,go,initialization,Struct,Go,Initialization,当我注意到以下代码段未编译时,我感到非常惊讶: aTime := time.Time{} if defaultTime := time.Time{} ; aTime != defaultTime {} 编译器返回: 键入时间。时间不是表达式 defaultTime:=时间。时间用作 未定义值:defaultTime 这里的目的是测试aTime变量是否设置为默认值 如果我得到结构的指针(defaultTime:=&time.time{}),它也不会编译 但是,如果I init defaultTi

当我注意到以下代码段未编译时,我感到非常惊讶:

aTime := time.Time{}
if defaultTime := time.Time{} ; aTime != defaultTime {}
编译器返回:

键入时间。时间不是表达式

defaultTime:=时间。时间用作

未定义值:defaultTime

这里的目的是测试aTime变量是否设置为默认值

如果我得到结构的指针(defaultTime:=&time.time{}),它也不会编译

但是,如果I init defaultTime在if构造之外,或者使用new()内置函数进行初始化,则它会编译:

从我到处读到的内容来看,new(myStruct)应该完全等同于&myStruct{}

正如我解释的那样,defaultValue:=time.time{}限定为a(特别是an),如中所述


尽管我尽了最大努力在谷歌上搜索,但我对这种行为没有任何解释。如果有人能让我的头停止转动,我将不胜感激。

代码>{被识别为
块的开始,终止对
SimpleStmt
的解析。提交该决定后,编译器决定,作为
SimpleStmt
aTime:=time.time
无效,因为
time.time
不是可以赋值的值。但是,它可能是太晚了,解析器无法尝试对
{
的另一种解释

带有
new
的版本之所以有效,是因为它不包含
{
字符,从而避免了以这种方式混淆解析器

还可以使用括号内的文字格式,因为块不能在表达式中间合法地开始,因此这也适用:

if defaultTime := (time.Time{}); aTime != defaultTime {
    // ...
}

gofmt
给出了有用的消息“期望的布尔表达式,找到的简单语句(复合文字周围缺少括号?)”,但奇怪的是,go编译器本身没有。我不认为我要建议的一定是更好的解决方案。但是对于您的用例,您可以尝试简洁一点

if !aTime.IsZero() {
    // ...
}

Ymmv

最好使用。例如
fmt.Println(time.time{}.IsZero())
prints
true
。感谢@icza的评论,我将使用它。该信息在复合文字部分()最后几段的Go规范中找到。查找“当出现解析歧义时”跳到正确的段落。好的,从技术上讲,这是go lexer中的一个bug/缺点?很高兴看到它被记录在案(尽管我没有找到它)。当不能使用新的时(对于需要设置字段的情况),包装看起来是一个可以接受的选择。谢谢!
if !aTime.IsZero() {
    // ...
}