如果在 Go 中构造,则无法初始化结构

Cannot init struct in if construct in Go

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

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

编译器returns:

type time.Time is not an expression

defaultTime := time.Time used as

value undefined: defaultTime

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

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

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

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

根据我到处阅读的内容,new(myStruct) 它应该完全等同于 &myStruct{}.

按照我的解释,defaultValue := time.Time{} 符合 SimpleStmt (specifically an Assignment), as detailed in the If statement spec.

尽管我尽了最大的谷歌搜索努力,但我仍未对这种行为做出任何解释。如果有人能让我的脑袋停止旋转,我将不胜感激。

{被识别为Block的开始,终止SimpleStmt的解析。在做出该决定后,编译器决定,作为 SimpleStmtaTime := time.Time 无效,因为 time.Time 不是可以分配的值。但是,解析器尝试对 {.

进行另一种解释可能为时已晚

带有 new 的版本可以工作,因为它不包含 { 字符,因此可以避免以这种方式混淆解析器。

您也可以通过将其括在括号中来使用文字格式,因为块不能合法地从表达式的中间开始,所以这也有效:

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

gofmt 给出了有用的信息 "expected boolean expression, found simple statement (missing parentheses around composite literal?)",但奇怪的是,go 编译器本身并没有。

我认为我要建议的不一定是更好的解决方案。但是对于你的用例,你可以尝试这样简洁

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

Ymmv