🚀 省流助手(速通结论)
- Struct 不是类:它只存数据,不存逻辑。逻辑通过“接收者(Receiver)”外挂实现,类似 JS 的
prototype。 - 没有
this:Go 显式命名接收者(如u),彻底解决了 TS 中this指向丢失的世纪难题。 - 权限全靠“吼”:首字母大写 =
public,首字母小写 =private。这是编译器级别的强制隔离。 - 赋值即复印:
a := b是物理深拷贝。想要引用?必须显式使用&拿钥匙(指针)。 - 契约严苛:函数要求指针(
*User)时,你传值(User)会直接编译报错,Go 不玩隐式转换。
1. 结构体不是类:数据与逻辑的彻底解耦
在 TS 中,class 是高度内聚的。但在 Go 中,struct 被剥离得只剩下数据描述。
TypeScript(内聚模型)
class User {
name: string;
constructor(name: string) { this.name = name; }
say() { console.log(this.name); } // 逻辑住在类里面
}
Go(数据模型)
type User struct {
Name string // 仅定义数据字段
}
// 逻辑通过外部函数“外挂”到 User 上
func (u User) Say() {
fmt.Println(u.Name)
}
🪝 思维钩子:Go 强迫你把“长什么样”和“能干什么”分开。你可以把 struct 看作是去掉了方法实现的“瘦身版” Class。
2. 方法的外挂艺术:再见了,迷之 this
TS 开发者最头疼的莫过于 this 绑定丢失。Go 根本不设 this 关键字,而是让你显式命名。
TypeScript(this 绑定焦虑)
const u = new User("Alice");
const say = u.say;
say(); // ❌ 报错:this 指向丢失(除非 bind 或用箭头函数)
Go(显式绑定)
// u 只是一个变量名,你可以叫它 self, me 或者 u
func (u User) Say() {
fmt.Println(u.Name) // u 的指向在定义时就写死了,永远不会丢
}
🪝 思维钩子:Go 的方法绑定极像 User.prototype.say = ...。这种设计让逻辑复用变得极其简单,且没有运行时的上下文陷阱。
3. 权限的大小写命令:最简单的隐藏规则
在 TS 中,我们写 private。在 Go 中,你只需按下 Shift 键。
TypeScript(关键字控制)
class User {
public name: string;
private age: number; // 靠关键字限制访问
}
Go(首字母定生死)
type User struct {
Name string // 首字母大写:外部包可见 (Public)
age int // 首字母小写:仅限本包可见 (Private)
}
🪝 思维钩子:这是 Go 的“行政命令”。如果你在 A 包定义了 age,在 B 包里你连提示都敲不出来。调用处必须严格遵守定义处的大小写,没有模糊地带。
4. 指针、原件与复印机:a := b 的终极实验
这是 TS 程序员转 Go 时最容易产生 Bug 的地方。在 TS 里,对象赋值是引用;在 Go 里,一切赋值皆拷贝。
TypeScript(自动引用)
const u1 = { name: "Alice" };
const u2 = u1;
u2.name = "Bob";
console.log(u1.name); // "Bob" (两人共用一个地址)
Go(默认复印机模式)
u1 := User{Name: "Alice"}
u2 := u1 // 发生物理拷贝!u2 是 u1 的一个完整副本
u2.Name = "Bob"
fmt.Println(u1.Name) // "Alice" (u1 根本没动)
u3 := &u1 // 这才是拿到了 u1 的钥匙(指针)
u3.Name = "Bob"
fmt.Println(u1.Name) // "Bob" (原件被修改了)
🪝 思维钩子:a := b 是盖了一座一模一样的房子;a := &b 是把房子的钥匙交出去。
5. 契约与传参:强指针约束
💡 注意:为了从 TS 视角更好理解 Go 的严谨性,请看下表。在 Go 中,类型契约是不可妥协的。
| 场景 | Go 表现 | 思维入口 |
|---|---|---|
函数要求 *User(指针) | 你传 User(值) | ❌ 编译报错:类型不匹配 |
函数要求 User(值) | 你传 *User(指针) | ❌ 编译报错:原件不能直接塞进复印机 |
🪝 思维钩子:Go 不支持隐式地址转换。当你写下 & 的那一刻,你在提醒自己:“我要交出修改原件的权限了”。
6. 工程组织:go.mod 对标 package.json
Go 的依赖管理不再有臃肿的 node_modules,它更清爽,但也更严格。
-
导入逻辑:Go 导入的是文件夹(Package),而不是单个文件。
-
版本管理:
go.mod≈package.json(记录主依赖版本)go.sum≈package-lock.json(记录哈希,防止内容篡改)
🪝 思维钩子:运行 go mod tidy 就像 npm install。它会自动扫描代码中的 import 路径,下载缺失包并剔除冗余包。
下篇预告:
我们将进入 Go 语言最迷人的部分:并发(Goroutine) 与 通道(Channel)。为什么 Go 处理万级并发轻而易举?为什么接口里不能定义变量?我们下篇见。