Golang自定义类型中"Used as value"错误处理
Golang自定义类型中"Used as value"错误处理 在使用自定义类型初始化 switch(或 for)语句时,我遇到了语法错误,我很可能遗漏了一些基础内容……请问您能帮忙看看吗?
package main
import (
"fmt"
)
func main() {
type f struct {a int}
newF := func(a int) f {
return f{a}
}
// 可以工作
switch x := newF(10); x.a {
case 10:
fmt.Println("OK")
}
// 可以工作
switch x := struct {a int}{10}; x.a {
case 10:
fmt.Println("OK")
}
// 语法错误
switch x := f{10}; x.a {
case 10:
fmt.Println("OK")
}
}
更多关于Golang自定义类型中"Used as value"错误处理的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢!不过,Go 语言能正确解析 x := struct {a int}{10},却在 x := f{10} 上出现混淆,这似乎有些奇怪。据我所见,两者都是有效的赋值(而 x := f 是无效的赋值,正如 x := struct {a int} 一样),并且都符合规范(https://golang.org/ref/spec#Switch_statements)。这值得作为 bug 上报吗?还是我遗漏了什么?
更多关于Golang自定义类型中"Used as value"错误处理的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个非常好的问题。
switch x := f{10}; x.a {
case 10:
fmt.Println("OK")
}
错误信息是:(参见 Go Playground)
./prog.go:26:15: 语法错误:x := f 被用作值 ./prog.go:27:2: 语法错误:意外的 case,期望表达式 ./prog.go:28:19: 语法错误:意外的 ),期望逗号或 }
问题在于 switch x := f{10}; 让解析器认为 {10} 是 ExprCaseClause(switch 语句的主体),因为 x := f 是一个有效的表达式。
解析器看到的是这样的:
switch x := f {
10
};
x := f 不能作为表达式,因为赋值和声明不返回值,这就是第一个错误出现的原因:语法错误:x := f 被用作值
你可以将其改为 x := (f{10}) 来使其正常工作。
顺便说一下,使用 x := struct {a int}{10} 可以正常工作,因为这不能被错误地拆分为 x := struct 或 x := struct {a int},因为那些是无效/不完整的表达式。
这是一个常见的语法问题。在Go语言中,当自定义类型作为复合字面量使用时,如果类型名称以大写字母开头(导出的类型),可以直接使用 TypeName{...} 的形式。但如果类型名称是小写的(未导出的类型),在复合字面量中需要显式指定类型名称。
在你的代码中,f 是一个小写的自定义类型,因此需要写成 f{a: 10} 或 f{10} 的形式,但在复合字面量中必须包含类型名称。
以下是修正后的代码:
package main
import (
"fmt"
)
func main() {
type f struct {a int}
newF := func(a int) f {
return f{a}
}
// 可以工作
switch x := newF(10); x.a {
case 10:
fmt.Println("OK")
}
// 可以工作
switch x := struct {a int}{10}; x.a {
case 10:
fmt.Println("OK")
}
// 修正后的语法
switch x := (f{10}); x.a {
case 10:
fmt.Println("OK")
}
// 或者使用显式字段名
switch x := f{a: 10}; x.a {
case 10:
fmt.Println("OK")
}
}
关键修正点是在 f{10} 外面加上括号 (f{10}),或者使用带字段名的初始化方式 f{a: 10}。这是因为在 switch 语句的初始化部分,编译器需要明确区分类型声明和复合字面量。
另一种更清晰的写法是:
// 先初始化变量再使用
x := f{10}
switch x.a {
case 10:
fmt.Println("OK")
}
这个问题的根本原因是Go语法解析器在处理 switch x := f{10}; ... 时,f{10} 可能被解析为类型转换而不是复合字面量。添加括号或使用带字段名的初始化可以消除歧义。

