Go不支持隐式类型转换,int与int64因类型独立、防溢出和平台差异而禁止直接相加;string与[]byte互转零拷贝但仅限UTF-8;interface{}须用带ok的类型断言;JSON反序列化需用json.RawMessage或自定义UnmarshalJSON处理类型不稳定;类型转换不校验值域,需业务层校验。
Go 语言不支持隐式类型转换,所有类型转换都必须显式声明,否则编译直接报错。
为什么 int 和 int64 不能直接相加?
Go 把不同整数类型视为完全独立的类型,哪怕底层存储相同(如 int 和 int64 在 64 位系统上都是 64 位),也不允许自动转换。这是为了防止溢出、平台差异和语义模糊。
- 错误写法:
a := 10; b := int64(20); c := a + b→ 编译报错:invalid operation: a + b (mismatched types int and int64) - 正确写法:统一转成同一类型,例如
c := int64(a) + b或c := a + int(a)(注意后者需确保值在int范围内) - 特别注意:
int的宽度依赖运行环境(32 位或 64 位),跨平台代码中优先使用明确宽度的类型,如int64、uint32
string 和 []byte 互转是否安全?
是安全的,且零拷贝(底层共享底层数组),但仅限 UTF-8 编码的字符串。转换本身不校验内容,如果字符串含非法 UTF-8 序列,转成 []byte 后仍保留原字节,后续按 UTF-8 解析可能出错。
-
str := "hello"; b := []byte(str)→ 安全,b是str的可变副本(注意:修改b不影响str,因为字符串不可变,实际会分配新底层数组) -
b := []byte{0xc3, 0x28}; s := string(b)→ 合法,但s包含非法 UTF-8,len(s)是 2,但utf8.RuneCountInString(s)会返回 1(首字节0xc3是两字节 UTF-8 起始,但第二字节0x28不符合格式) - 若需校验,用
utf8.Valid检查后再转
如何把 interface{} 安全转成具体类型?
必须用类型断言(type assertion),且推荐带 ok-idiom 形式,避免 panic。直接断言失败会 panic,仅适用于你 100% 确定类型时(如内部已做过判断)。