对象模型与内存的“钥匙理论”:TS 切入的 Go 的结构体与指针

🚀 省流助手(速通结论)

  • Struct 不是类:它只存数据,不存逻辑。逻辑通过"接收者(Receiver)"外挂实现,类似 JS 的 prototype
  • 没有 this:Go 显式命名接收者(如 u),彻底解决了 TS 中 this 指向丢失的世纪难题。
  • 权限全靠"吼":首字母大写 = public,首字母小写 = private。这是编译器级别的强制隔离。
  • 赋值即复印:a := b 是物理深拷贝。想要引用?必须显式使用 & 拿钥匙(指针)。
  • 契约严苛:函数要求指针(*User)时,你传值(User)会直接编译报错,Go 不玩隐式转换。

1. 结构体不是类:数据与逻辑的彻底解耦

在 TS 中,class 是高度内聚的。但在 Go 中,struct 被剥离得只剩下数据描述。

TypeScript(内聚模型)

typescript 复制代码
class User {
    name: string;
    constructor(name: string) { this.name = name; }
    say() { console.log(this.name); } // 逻辑住在类里面
}

Go(数据模型)

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 绑定焦虑)

ini 复制代码
const u = new User("Alice");
const say = u.say;
say(); // ❌ 报错:this 指向丢失(除非 bind 或用箭头函数)

Go(显式绑定)

scss 复制代码
// u 只是一个变量名,你可以叫它 self, me 或者 u
func (u User) Say() {
    fmt.Println(u.Name) // u 的指向在定义时就写死了,永远不会丢
}

🪝 思维钩子:Go 的方法绑定极像 User.prototype.say = ...。这种设计让逻辑复用变得极其简单,且没有运行时的上下文陷阱。


3. 权限的大小写命令:最简单的隐藏规则

在 TS 中,我们写 private。在 Go 中,你只需按下 Shift 键。

TypeScript(关键字控制)

typescript 复制代码
class User {
    public name: string;
    private age: number; // 靠关键字限制访问
}

Go(首字母定生死)

go 复制代码
type User struct {
    Name string // 首字母大写:外部包可见 (Public)
    age  int    // 首字母小写:仅限本包可见 (Private)
}

🪝 思维钩子:这是 Go 的"行政命令"。如果你在 A 包定义了 age,在 B 包里你连提示都敲不出来。调用处必须严格遵守定义处的大小写,没有模糊地带。


4. 指针、原件与复印机:a := b 的终极实验

这是 TS 程序员转 Go 时最容易产生 Bug 的地方。在 TS 里,对象赋值是引用;在 Go 里,一切赋值皆拷贝。

TypeScript(自动引用)

ini 复制代码
const u1 = { name: "Alice" };
const u2 = u1; 
u2.name = "Bob";
console.log(u1.name); // "Bob" (两人共用一个地址)

Go(默认复印机模式)

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.modpackage.json(记录主依赖版本)
    • go.sumpackage-lock.json(记录哈希,防止内容篡改)

🪝 思维钩子:运行 go mod tidy 就像 npm install。它会自动扫描代码中的 import 路径,下载缺失包并剔除冗余包。


下篇预告:

我们将进入 Go 语言最迷人的部分:并发(Goroutine) 与 通道(Channel)。为什么 Go 处理万级并发轻而易举?为什么接口里不能定义变量?我们下篇见。

相关推荐
阿正的梦工坊2 小时前
JavaScript 函数组合(Compose & Pipe)详解
开发语言·javascript·网络
冴羽yayujs3 小时前
2026 年的 JavaScript 已经不是你认识的 JavaScript 了
前端·javascript
M ? A3 小时前
你的 Vue v-for,VuReact 会编译成什么样的 React 代码?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
午安~婉3 小时前
Electron桌面应用(续3)
前端·javascript·electron·重构通用模型·异步可迭代对象
W.A委员会3 小时前
伪类与伪元素
前端·javascript·css
午安~婉3 小时前
Electron桌面应用(续2)
前端·javascript·electron·路由守卫·优化llm返回的内容
weixin_443478513 小时前
Flutter学习之自定义组件
javascript·学习·flutter
编程牛马姐12 小时前
独立站SEO流量增长:提高Google排名的优化方法
前端·javascript·网络
我叫黑大帅12 小时前
通过eino-ext如何正常indexer RAG?
后端·面试·go