在Go语言中实现了静态严格类型。也就是说,每个变量的类型在编译时是已知的,编译器不允许对不兼容的类型执行操作。
有两种类型转换:
显式转换示例:
var i int = 42 var f float64 = float64(i)
类型断言示例:
var i interface{} = "hello" s, ok := i.(string) if ok { fmt.Println("字符串值:", s) } else { fmt.Println("i 不是字符串") }
转换只能在兼容的基本类型之间进行(int → float64,rune → int32,但string → int 是不可能的)。
interface{} 能否存储 nil 值,如何正确检查接口类型的变量是否真的为 nil?
常见的陷阱是直接将包含 nil 值的接口与 nil 进行比较:
var err error = nil var i interface{} = err fmt.Println(i == nil) // 预计为 true,但实际上是 false!
正确的方法:
检查接口本身和内嵌值是否为 nil:
if i == nil || reflect.ValueOf(i).IsNil() { fmt.Println("i 的确为 nil") }
故事
在一个后端项目中,开发者试图通过 interface{} 处理不同的错误,与 nil 进行比较。结果,错误无法被正确检测到 — 出现了隐蔽的 bug 和错误的错误返回逻辑给客户端。
故事
在 float64 和 int 之间迁移而没有显式的 cast 导致了静默的数据丢失:值被错误地四舍五入或转移,因为 Go 编译器要求此类操作进行显式转换。
故事
在处理 map[string]interface{}(例如,从 JSON 中)的接口值反序列化时,意外的数字类型(float64)在没有额外检查 ok 的情况下使用类型断言时导致 panic — 服务因运行时错误而崩溃。