文章目录
- [基本类型 & struct](#基本类型 & struct)
-
- 核心概念
- struct(最重要)
- 关键点
-
- [1. 字段必须大写才能被外部访问](#1. 字段必须大写才能被外部访问)
- [2. JSON tag](#2. JSON tag)
- 工程用法
- 函数
- [slice / map](#slice / map)
-
- slice(动态数组)
- [slice 是引用类型](#slice 是引用类型)
- map(字典)
- [map 必须初始化](#map 必须初始化)
- 工程用法
- [error 处理(Go 最核心思想)](#error 处理(Go 最核心思想))
- interface
- [总结:5 个认知](#总结:5 个认知)
-
- [struct 是一切的核心](#struct 是一切的核心)
- [error 是"第一等公民"](#error 是“第一等公民”)
- [没有 OOP 那套复杂东西](#没有 OOP 那套复杂东西)
- [interface 是"解耦工具",不是抽象炫技](#interface 是“解耦工具”,不是抽象炫技)
- [代码风格 = 简单 + 显式](#代码风格 = 简单 + 显式)
在 HOW - Go 开发入门(一) 我们进行了开发入门的开篇介绍。今天我们主要介绍第 1 步。
基本类型 & struct
Go 的"数据模型"
核心概念
Go 是强类型语言:
go
var a int = 10
b := "hello" // 自动推导
常见类型:
int / int64float64stringbool
struct(最重要)
类似 TS 的 interface + class(但更简单):
go
type User struct {
ID int
Name string
Age int
}
使用:
go
u := User{
ID: 1,
Name: "Tom",
Age: 18,
}
关键点
1. 字段必须大写才能被外部访问
尤其 JSON。
go
type User struct {
Name string // ✅ 可导出
age int // ❌ 外部访问不到
}
这点坑很多人(特别是做 API 时)。
2. JSON tag
做接口必用。
go
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
工程用法
- struct = DB model(GORM)
- struct = API request/response
- struct = 配置对象
函数
Go 的函数很"朴素但强大"。
基本写法
go
func add(a int, b int) int {
return a + b
}
简写:
go
func add(a, b int) int {
return a + b
}
多返回值
Go 精髓。
go
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("divide by zero")
}
return a / b, nil
}
使用:
go
res, err := divide(10, 2)
关键点:没有异常机制
Go 没有异常机制(try/catch),全靠返回值:
所以你会看到:
go
if err != nil {
return err
}
工程用法
- 所有 IO / DB / API 都返回
(result, error) - 函数尽量短小(Go 风格)
slice / map
最常用容器。
slice(动态数组)
go
nums := []int{1, 2, 3}
追加:
go
nums = append(nums, 4)
遍历:
go
for i, v := range nums {
fmt.Println(i, v)
}
slice 是引用类型
go
a := []int{1, 2, 3}
b := a
b[0] = 100
fmt.Println(a) // [100 2 3]
很容易踩坑
map(字典)
go
m := map[string]int{
"a": 1,
"b": 2,
}
访问:
go
v, ok := m["a"]
map 必须初始化
go
var m map[string]int
m["a"] = 1 // ❌ panic
正确:
go
m := make(map[string]int)
工程用法
- slice = 列表数据(接口返回)
- map = 配置 / 索引 / 快速查找
error 处理(Go 最核心思想)
这是 Go 和其他语言最大差异。
标准写法
go
res, err := doSomething()
if err != nil {
return err
}
自定义 error
go
return errors.New("something wrong")
或:
go
fmt.Errorf("user %d not found", id)
关键哲学
Go 的理念:
错误是"值",不是"异常"
所以:
- 不要 try/catch
- 不要隐藏错误
- 必须显式处理
工程最佳实践
1. wrap error
go
if err != nil {
return fmt.Errorf("query user failed: %w", err)
}
2. 统一错误处理
在 Web 框架里。比如用 Gin:
go
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
interface
理解即可,但非常关键。
Go 的 interface 和 TS 完全不同。
定义
go
type Animal interface {
Speak() string
}
实现(隐式实现)
go
type Dog struct{}
func (d Dog) Speak() string {
return "wang"
}
不需要 implements!具备解耦系统、易替换实现的优势。
使用
go
func makeSound(a Animal) {
fmt.Println(a.Speak())
}
核心理解
Go 是:
鸭子类型(Duck Typing)
只要实现方法,就自动满足接口。
工程用法
- 抽象服务(Repository / Service)
- 解耦依赖(类似 TS interface)
- mock 测试
总结:5 个认知
要建立这 5 个认知:
struct 是一切的核心
- 代替 class
- 代替 DTO
- 代替 schema
error 是"第一等公民"
看到代码:
go
if err != nil
这是正常,不是啰嗦
没有 OOP 那套复杂东西
- 没有继承
- 没有泛型复杂设计(虽然现在支持,但少用)
OOP,面向对象,不是"更先进",而是"在某些场景更合适"。虽然 Go 刻意弱化 OOP,但依然能写大型系统。
OOP = 把"数据 + 行为"绑定在一起,将数据和行为绑定,具备封装、继承复用、多态(同一个接口不同实现)等优势。
但是,OOP 同样存在过度设计(类太多、层级复杂、理解成本高)、继承滥用(强耦合、修改困难)、抽象过早等问题。
| 能力 | OOP(Java/TS) | Go |
|---|---|---|
| 封装 | class | struct + 方法 |
| 继承 | 有 | ❌(用组合) |
| 多态 | interface + implements | interface(隐式) |
| 抽象 | 强 | 简单直接 |