go变量类型由编译器严格推导,非默认设定;短变量声明仅限函数内;零值确定;interface{}是类型擦除起点,需断言使用;数组与切片类型不兼容;struct字段首字母大小写决定导出性。

Go 里变量声明不写类型,但编译器早就“看透”了
Go 的变量类型不是靠人猜的,是编译期严格推导出来的。你写 var x = 42,x 就是 int;写 var y = 3.14,y 就是 float64。这不是“默认”,是类型推导(type inference)——它发生在编译时,没有运行时开销,也不模糊。
常见错误现象:var n = 1000000000000000000 在 32 位系统上可能意外变成 int64,但如果你后续把它传给只接受 int 的函数,就会报错:cannot use n (type int64) as type int。这不是 bug,是类型系统在拦你。
- 短变量声明
:=只能在函数内用,包级变量必须用var -
var x int = 42和x := 42在函数内等价,但后者更常用;前者在需要显式指定类型(比如var buf bytes.Buffer)时不可替代 - 零值不是“未初始化”,而是确定的:数值是
0,字符串是"",指针是nil,切片/映射/通道也是nil
interface{} 不是万能兜底,它是类型擦除的起点
写 func print(v interface{}) 看似能接一切,但调用时 v 已经丢失原始类型信息。你不能直接对 v 做加法、取长度或调方法——得先类型断言或类型切换。
使用场景:通用日志、序列化入口、反射前的参数中转。但它不是设计目标,而是妥协手段。
- 类型断言失败会 panic:
s := v.(string)—— 更安全写法是s, ok := v.(string) - 用
switch t := v.(type)处理多类型分支时,t是新变量,类型由 case 决定,不是interface{} - 把
int赋给interface{},底层会分配新内存存值(值拷贝),不是指针传递
切片和数组混用时,类型不兼容是硬规则
[3]int 和 []int 是完全不同的类型,不能互相赋值,也不能当同一函数参数传。Go 不做隐式转换,哪怕长度一样。
常见错误现象:定义了 var a [3]int,想传给接收 []int 的函数,直接写 f(a) 报错:cannot use a (type [3]int) as type []int。
- 转成切片用
a[:],这是合法且零拷贝的(共享底层数组) -
[...]int{1,2,3}中的...是数组长度推导语法,不是可变参数;它生成的是数组字面量,不是切片 - 切片头结构含指针+长度+容量,数组是固定内存块;传数组是值拷贝,传切片是头结构拷贝(轻量)
struct 字段首字母大小写决定是否导出,不是风格问题
字段名以大写字母开头(如 Name)才可在其他包访问;小写(如 name)即私有。这不是 lint 规则,是 Go 编译器强制的可见性边界。
容易踩的坑:用 json.Marshal 序列化 struct,发现小写字段没输出——因为它们不可导出,反射拿不到。
- JSON tag(如
json:"user_name")只影响序列化行为,不改变字段可见性 - 嵌入字段(anonymous field)的导出性也遵循同样规则:大写才被提升(promoted)
- 不要为了导出而改名;该封装就封装,该暴露就暴露,名字本身应表达意图,不是迁就导出规则
类型系统不是语法装饰,它从变量声明那一刻就开始约束行为。写错一个字母大小写、漏一个 :、少一个 &,都可能让编译器立刻叫停——这不是阻碍,是提前把模糊地带清掉。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











