

新闻资讯
技术百科Go中表达式产生值、语句执行动作不返回值;i++是语句故不可用于赋值右边,须拆为取值再自增,以此规避求值顺序歧义。
Go 语言中,语句和表达式有本质区别:**表达式产生值,语句执行动作但不返回值**。这不是语法细节,而是影响你能否写出合法、可读、无歧义代码的关键分水岭。
i++ 不能写在赋值右边?因为 ++ 和 -- 在 Go 中是语句,不是表达式——它不返回任何值。这和 C/C++/Java 完全不同。
i++ 是一条独立语句,作用是“让 i 自增 1”,没有返回值j := i++ 会报错:invalid operation: i++ (non-name i) 或更直白的 syntax error: unexpected ++
i := 0 j := i // 先取值 i++ // 再自增
f(i++, i++) 这类求值顺序未定义的陷阱,Go 直接不让它存在判断标准很简单:**能不能放在 = 右边、if 条件里、函数调用参数中?能,就是表达式;不能,大概率是语句。**
42、x + y、len(s)、strings.ToUpper("go")、m["key"]、&v
if x > 0 { ... }、for i := 0; i 、return err、var s string、i++
defer f()、go f()、select {...} 都是语句,哪怕它们内部包含函数调用(f() 是表达式,但整个 go f() 不是)方法调用是否属于表达式,取决于它是否返回值,以及你用的是 method value 还是 method expression:
obj.Method() 是表达式(如果 Method 有返回值),可以赋值:s := user.GetName() // 合法,GetName() 返回 string
(*T).Method 是函数值(表达式),可赋给变量或传参:f := (*User).Save f(&user, db) // 合法
user.Save() 本身只是语句(如果 Save 返回 error 且你没接收):user.Save() // 语句;若忽略 error,属危险操作
json.Unmarshal)当纯表达式用,却忘了它要传指针且可能失败最易被忽略的一点:Go 的 if 和 switch 支持「短变量声明」,比如 if x := getValue(); x > 0 { ... }——这里的 x := getValue() 是语句,而 x > 0 才是表达式。很多人误以为整行都是表达式,结果在 for 初始化部分写 for x := 0; x 时,下意识想写成 for x ,却忘了中间分号后只能是布尔表达式,不能是语句。
:= getValue(); x > 0; x++