Go 中 struct 类型不能直接赋值:正确声明和初始化结构体变量的方法

在 go 中,`var s = salutation` 会报错“type salutation is not an expression”,因为 `salutation` 是类型名而非可求值的表达式;必须使用 `salutation{}` 或带字段的字面量进行初始化。

Go 是一门强类型、静态编译的语言,其变量声明与初始化语义严格区分「类型」和「值」。当你写下:

var s = Salutation

编译器会尝试将右侧 Salutation 视为一个可求值的表达式(例如字面量、函数调用或已有变量),但 Salutation 仅是一个类型标识符,不产生任何运行时值——因此触发错误:type Salutation is not an expression。

✅ 正确做法是显式构造该类型的零值实例初始化实例。以下是三种等效且合法的声明方式:

1. 声明类型,隐式零值初始化(推荐用于包级变量)

var s Salutation
s.name = "Alex"
s.greeting = "Hi"

此时 s 被声明为 Salutation 类型,自动初始化为零值(即 name 和 greeting 均为空字符串)。

2. 使用结构体字面量创建零值({} 表示所有字段取零值)

var s = Salutation{} // ✅ 合法:Salutation{} 是表达式,结果为 Salutation 类型的零值
s.name = "Alex"
s.greeting = "Hi"

3. 短变量声明(最常用,限于函数内)

s := Salutation{} // ✅ 推荐写法;Go 自动推导类型为 Salutation
s.name = "Alex"
s.greeting = "Hi"

? 更进一步,你完全可以将声明与字段初始化合并,提升可读性与安全性(避免遗漏字段):

s := Salutation{
    name:     "Alex",
    greeting: "Hi",
}
Greet(s)

或使用位置式初始化(需严格按字段顺序):

s := Salutation{"Alex", "Hi"} // 有效,但可读性较低,不推荐用于含多个字段的 struct

⚠️ 注意事项:

  • var s = Salutation{"Alex", "Hi"} 虽然能通过编译,但依赖字段顺序,易出错;命名字段初始化({name: ..., greeting: ...})更清晰、更健壮
  • 包级变量(全局变量)不能使用 :=,只能用 var 声明。
  • 结构体字段若未导出(小写首字母,如 name),在其他包中不可访问——本例中 Greet 函数在同一包内,无影响,但设计 API 时需注意导出规则。

总结:Go 不允许将类型名直接当作值使用。要获得结构体实例,必须通过 Type{}、Type{field: value} 或 &Type{} 等字面量语法构造具体值。理解「类型 ≠ 值」是掌握 Go 变量模型的关键一步。