Python 开发者的 Golang 完全入门指南

从动态到静态,从解释到编译,开启你的 Go 之旅


目录

  1. [为什么选 Go?](#为什么选 Go? "#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89-go")
  2. 环境搭建
  3. [Hello World 对比](#Hello World 对比 "#hello-world-%E5%AF%B9%E6%AF%94")
  4. 基础语法差异
  5. 数据类型详解
  6. 控制结构
  7. 函数与多返回值
  8. 结构体与方法
  9. 接口与多态
  10. [并发编程:Goroutine 与 Channel](#并发编程:Goroutine 与 Channel "#%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B")
  11. 错误处理
  12. 标准库常用包
  13. 工程化实践
  14. [从 Python 到 Go 的思维转换](#从 Python 到 Go 的思维转换 "#%E6%80%9D%E7%BB%B4%E8%BD%AC%E6%8D%A2")

为什么选 Go? {#为什么选-go}

特性 Python Go 场景优势
执行速度 解释型,较慢 编译型,接近C++ 高性能后端、微服务
并发模型 GIL限制,多线程假并行 Goroutine,原生支持高并发 云原生、网络编程
部署 需解释器/虚拟环境 单二进制文件,静态链接 容器化、Serverless
类型系统 动态类型,灵活但易出错 静态类型,编译期检查 大型项目、团队协作
内存管理 自动GC,但优化空间有限 自动GC,性能调优更可控 长期运行服务
生态定位 全能型(AI/脚本/Web) 云原生/基础设施/中间件 Docker/K8s/Etcd 都是用 Go 写的

Go 的最佳战场:微服务、API 网关、DevOps 工具、区块链基础设施、实时数据处理。


环境搭建 {#环境搭建}

安装 Go(以 Linux/macOS 为例)

bash 复制代码
# 下载安装包 (1.21+ 版本)
wget https://go.dev/dl/go1.21.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz

# 配置环境变量
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc

# 验证
go version  # go version go1.21.5 linux/amd64

工作区模式(Go Modules,1.11+ 推荐)

bash 复制代码
# 创建项目(无需放在 GOPATH/src 下)
mkdir myproject && cd myproject
go mod init github.com/yourname/myproject

# 目录结构
myproject/
├── go.mod          # 依赖管理文件
├── go.sum          # 依赖校验和
├── main.go         # 入口文件
├── pkg/            # 可复用包
└── internal/       # 私有包(不可被外部导入)

常用命令

bash 复制代码
go run main.go          # 编译并运行(不生成二进制)
go build                # 编译生成可执行文件
go build -o app         # 指定输出文件名
go test ./...           # 运行所有测试
go get github.com/gin-gonic/gin  # 添加依赖
go mod tidy             # 清理未使用依赖

Hello World 对比 {#hello-world-对比}

Python 版本

python 复制代码
# hello.py
def main():
    name = "World"
    print(f"Hello, {name}!")

if __name__ == "__main__":
    main()

运行python hello.py

Go 版本

go 复制代码
// main.go
package main  // 可执行程序必须是 main 包

import "fmt"  // 格式化 I/O,类似 Python 的 print

func main() {  // 程序入口,无参数,无返回值
    name := "World"  // 短变量声明,类型推断为 string
    fmt.Printf("Hello, %s!\n", name)  // 格式化输出,\n 必须显式添加
}

运行go run main.gogo build && ./main

关键差异

  • package main:可执行程序的入口包,库文件则用其他名(如 package utils
  • import:必须显式导入,未使用的包会编译错误(强制代码整洁)
  • :=:短变量声明,只能在函数内使用,自动推断类型
  • fmt.Printf:格式化字符串,类似 C 的 printf,Go 中字符串插值需用格式化动词

基础语法差异 {#基础语法差异}

1. 变量声明

go 复制代码
// Go 的多种声明方式
var x int = 10           // 完整声明
var y = 20               // 类型推断
var z int                // 零值初始化(z = 0)
a := 30                  // 短声明,只能在函数内

// 多变量
var a, b, c = 1, 2, 3
m, n := "hello", 42      // 不同类型同时推断

// 对比 Python:x, y, z = 10, 20, 30(动态类型,无需声明)

零值机制(Go 的哲学:没有未初始化的变量):

  • 数值类型:0
  • 布尔:false
  • 字符串:""(空字符串,非 None)
  • 指针、slice、map、channel:nil(类似 None,但类型安全)

2. 常量与枚举

go 复制代码
const Pi = 3.14159       // 常量,编译期确定
const (
    Monday = iota        // iota 枚举生成器,从 0 开始自增
    Tuesday              // 1
    Wednesday            // 2
    // ...
)

// 对比 Python:没有原生常量,通常用大写+下划线约定
# PYTHON_CONST = 100  # 只是约定,仍可修改

3. 可见性规则(重要!)

go 复制代码
package mypkg

// 大写字母开头 = 公开(public)
func PublicFunction() {}    // 可被其他包导入使用
var PublicVar = 10

// 小写字母开头 = 私有(private)
func privateFunction() {}   // 仅在 mypkg 包内可见
var privateVar = 20

// 对比 Python:_前缀表示私有,但只是约定,技术上仍可访问
# def _private_func(): pass

Go 的可见性由命名控制,无 public/private 关键字,这是 Go 极简设计的体现。


数据类型详解 {#数据类型详解}

1. 基础类型

Go 类型 说明 Python 对应
int 至少32位,通常是64位 int(无上限)
int8/16/32/64 固定位宽 无直接对应
uint 无符号整数 无直接对应
float32/64 浮点数 float
string 不可变 UTF-8 字符串 str(不可变)
bool true/false True/False
byte uint8 别名 单个字节
rune int32 别名,表示 Unicode 码点 类似 ord(char)
go 复制代码
// 字符串操作(对比 Python)
s := "Hello, 世界"
fmt.Println(len(s))        // 13 字节数(UTF-8 编码)
fmt.Println(len([]rune(s))) // 9 字符数(Unicode 码点数)

// 字符串不可变!类似 Python
// s[0] = 'h'  // 编译错误

// 切片操作(类似 Python slicing,但语法不同)
substr := s[0:5]  // "Hello",左闭右开

2. 复合类型

数组(Array)- 固定长度,值类型

go 复制代码
var arr [5]int = [5]int{1, 2, 3, 4, 5}  // 长度是类型的一部分!
arr2 := [...]int{1, 2, 3}               // 编译器推断长度 [3]int

// 数组是值类型,赋值会复制整个数组
b := arr  // 复制 5 个 int 的内存
b[0] = 100
fmt.Println(arr[0])  // 1(原数组未变)

// 对比 Python:list 是引用类型
# a = [1, 2, 3]
# b = a
# b[0] = 100
# print(a[0])  # 100

切片(Slice)- 动态数组,引用类型 ⭐核心概念

go 复制代码
// 切片是描述符:[指针, 长度, 容量],指向底层数组
slice := []int{1, 2, 3}           // 字面量创建
slice2 := make([]int, 5)          // 长度5,容量5,零值初始化
slice3 := make([]int, 5, 10)      // 长度5,容量10

// 追加元素(类似 Python append,但语法不同)
slice = append(slice, 4, 5)       // 可能触发底层数组扩容

// 切片共享底层数组(危险但高效)
a := []int{1, 2, 3, 4, 5}
b := a[1:3]  // [2, 3]
b[0] = 100
fmt.Println(a)  // [1, 100, 3, 4, 5]  // 原数组被修改!

// 深拷贝
c := make([]int, len(a))
copy(c, a)   // 显式拷贝

// 对比 Python:切片默认浅拷贝,但 list 是可变对象
# a = [1, 2, 3, 4, 5]
# b = a[1:3]
# b[0] = 100
# print(a)  # [1, 2, 3, 4, 5]  Python 切片创建新列表!

关键区别:Go 切片是引用类型,共享底层数组;Python 切片创建新列表。

映射(Map)- 类似 Python dict

go 复制代码
// 必须 make 初始化(或字面量)
m := make(map[string]int)
m["alice"] = 25
m["bob"] = 30

// 字面量创建
m2 := map[string]int{
    "alice": 25,
    "bob": 30,
}

// 访问与检查存在性
age, ok := m["charlie"]  // age=0, ok=false(零值 + 布尔标志)
if ok {
    fmt.Println("存在,年龄", age)
}

// 删除
delete(m, "alice")

// 遍历(无序!)
for key, value := range m {
    fmt.Printf("%s: %d\n", key, value)
}

// 对比 Python:有序字典(3.7+),get 方法,in 关键字
# age = m.get("charlie")  # None
# if "charlie" in m:

3. 结构体(Struct)- 代替 Python 的 Class

go 复制代码
// 定义结构体(值类型)
type Person struct {
    Name string
    Age  int
    // 小写字段私有,大写公开
    email string  // 包内私有
}

// 创建实例(多种方式)
p1 := Person{"Alice", 25, "alice@example.com"}  // 按字段顺序
p2 := Person{Name: "Bob", Age: 30}               // 命名初始化,email 为零值
p3 := new(Person)                                // 返回 *Person,零值初始化

// 访问字段
fmt.Println(p1.Name)
p1.Age = 26

// 对比 Python class
# class Person:
#     def __init__(self, name, age):
#         self.name = name
#         self.age = age
# p = Person("Alice", 25)

控制结构 {#控制结构}

1. 条件语句

go 复制代码
// if 支持初始化语句(常见模式)
if err := doSomething(); err != nil {
    return err
}
// err 的作用域仅在 if 块内

// 无括号,必须花括号
if x > 0 {
    fmt.Println("positive")
} else if x < 0 {
    fmt.Println("negative")
} else {
    fmt.Println("zero")
}

// 对比 Python:elif,冒号+缩进
# if x > 0:
#     print("positive")
# elif x < 0:
#     print("negative")

2. 循环(Go 只有 for,无 while)

go 复制代码
// 类 C 风格
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

// 类 while 风格
sum := 0
for sum < 100 {
    sum += 10
}

// 无限循环
for {
    // do something
    break  // 或 return
}

// 遍历 slice(range 返回索引, 值)
nums := []int{10, 20, 30}
for i, v := range nums {
    fmt.Printf("index: %d, value: %d\n", i, v)
}

// 只需要值:用 _ 忽略索引
for _, v := range nums {
    fmt.Println(v)
}

// 遍历 map
for k, v := range m {
    fmt.Println(k, v)
}

// 对比 Python:for/while,enumerate,items()
# for i, v in enumerate(nums):
#     print(i, v)
# for k, v in d.items():

3. Switch(强大且灵活)

go 复制代码
// 自动 break,无需显式写
switch os := runtime.GOOS; os {
case "darwin":
    fmt.Println("macOS")
case "linux":
    fmt.Println("Linux")
default:
    fmt.Println("其他")
}

// 无表达式 switch(替代 if-else if)
score := 85
switch {
case score >= 90:
    fmt.Println("A")
case score >= 80:
    fmt.Println("B")
default:
    fmt.Println("C")
}

// fallthrough 穿透(很少用)
switch n {
case 1:
    fmt.Println("1")
    fallthrough  // 继续执行 case 2
case 2:
    fmt.Println("2")
}

函数与多返回值 {#函数与多返回值}

1. 基础函数

go 复制代码
// 函数签名:func 函数名(参数) (返回值)
func add(a int, b int) int {
    return a + b
}

// 同类型参数可合并
func add(a, b int) int {
    return a + b
}

// 多返回值(Go 特色!)
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("cannot divide by zero")
    }
    return a / b, nil
}

// 使用
result, err := divide(10, 0)
if err != nil {
    log.Fatal(err)
}
fmt.Println(result)

// 忽略返回值
result, _ = divide(10, 2)  // 忽略 error(不推荐,除非确定安全)

// 对比 Python:多返回值用 tuple,异常处理不同
# def divide(a, b):
#     if b == 0:
#         raise ValueError("cannot divide by zero")
#     return a / b, None
# try:
#     result = divide(10, 0)
# except ValueError as e:
#     print(e)

2. 命名返回值(较少用,但可读性好)

go 复制代码
func split(sum int) (x, y int) {  // 命名返回值
    x = sum * 4 / 9
    y = sum - x
    return  // 裸 return,返回命名变量
}

3. 变长参数

go 复制代码
func sum(nums ...int) int {  // ... 类似 Python *args
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

// 使用
sum(1, 2, 3)
nums := []int{1, 2, 3}
sum(nums...)  // 展开 slice,类似 Python *nums

4. 函数是一等公民(类似 Python)

go 复制代码
// 函数作为参数(回调)
func apply(nums []int, f func(int) int) []int {
    result := make([]int, len(nums))
    for i, v := range nums {
        result[i] = f(v)
    }
    return result
}

// 使用
squares := apply([]int{1, 2, 3}, func(x int) int {
    return x * x
})

// 闭包
func makeCounter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

counter := makeCounter()
fmt.Println(counter())  // 1
fmt.Println(counter())  // 2

结构体与方法 {#结构体与方法}

1. 方法定义(值接收者 vs 指针接收者)

go 复制代码
type Rectangle struct {
    Width, Height float64
}

// 值接收者:方法内是副本修改,不影响原对象
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// 指针接收者:可以修改原对象,避免大对象拷贝
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

// 使用
rect := Rectangle{10, 5}
fmt.Println(rect.Area())    // 50
rect.Scale(2)               // 修改原对象
fmt.Println(rect.Width)     // 20

// 对比 Python:self 总是引用,无值/指针区分
# class Rectangle:
#     def area(self):
#         return self.width * self.height
#     def scale(self, factor):
#         self.width *= factor  # 总是修改原对象

选择规则

  • 不修改状态且对象小 → 值接收者
  • 需要修改状态或对象大 → 指针接收者

2. 嵌入类型(类似继承,但更好)

go 复制代码
type Animal struct {
    Name string
}

func (a *Animal) Speak() {
    fmt.Println("Some sound")
}

// Dog 嵌入 Animal,获得其字段和方法
type Dog struct {
    Animal  // 匿名嵌入,非继承!
    Breed   string
}

// 可以重写方法
func (d *Dog) Speak() {
    fmt.Println("Woof!")
}

// 使用
d := Dog{Animal: Animal{Name: "Buddy"}, Breed: "Golden"}
d.Speak()        // Woof!(Dog 的方法)
d.Animal.Speak() // Some sound(Animal 的方法)
fmt.Println(d.Name)  // Buddy,直接访问嵌入字段

// 对比 Python 继承
# class Animal:
#     def speak(self): print("Some sound")
# class Dog(Animal):
#     def speak(self): print("Woof!")

关键区别 :Go 的嵌入是组合而非继承,无多态(需通过接口实现)。


接口与多态 {#接口与多态}

1. 隐式实现(Go 的革命性设计)

go 复制代码
// 定义接口:只需声明方法签名
type Speaker interface {
    Speak()
}

// Dog 自动实现 Speaker(无需 implements 关键字)
type Dog struct{}
func (d Dog) Speak() { fmt.Println("Woof") }

type Cat struct{}
func (c Cat) Speak() { fmt.Println("Meow") }

// 多态使用
func MakeSound(s Speaker) {
    s.Speak()
}

MakeSound(Dog{})  // Woof
MakeSound(Cat{})  // Meow

// 对比 Python:鸭子类型,无显式接口
# def make_sound(animal):
#     animal.speak()  # 运行时检查,无编译期保障

Go 接口优势

  • 隐式实现:解耦接口定义与实现
  • 编译期检查:类型安全
  • 小接口原则:接口应该小(1-3 个方法),组合使用

2. 空接口与类型断言

go 复制代码
// 空接口 interface{} 类似 Python 的 Any,可接受任何类型
func PrintAny(v interface{}) {
    fmt.Println(v)
}

// 类型断言(类似 Python isinstance)
func process(v interface{}) {
    // 方式1:安全断言
    if s, ok := v.(string); ok {
        fmt.Println("String:", s)
        return
    }
    
    // 方式2:switch 类型判断
    switch val := v.(type) {
    case int:
        fmt.Println("Int:", val)
    case string:
        fmt.Println("String:", val)
    default:
        fmt.Println("Unknown type")
    }
}

// Go 1.18+ 泛型(推荐替代空接口)
func Add[T int | float64](a, b T) T {
    return a + b
}

并发编程 {#并发编程}

这是 Go 的杀手锏!对比 Python 的 threading/multiprocessing,Go 的并发极其简单高效。

1. Goroutine - 轻量级线程

go 复制代码
// 启动一个 goroutine(只需 go 关键字)
func sayHello() {
    fmt.Println("Hello from goroutine")
}

go sayHello()  // 非阻塞,立即返回

// 匿名函数形式
go func() {
    fmt.Println("Anonymous goroutine")
}()

// 对比 Python:需要 threading.Thread
# import threading
# t = threading.Thread(target=say_hello)
# t.start()

关键差异

  • Python 线程:OS 线程,切换成本高,GIL 限制真并行
  • Goroutine:用户态线程,2KB 初始栈,Go 调度器管理,可轻松启动百万级

2. Channel - goroutine 间的通信

go 复制代码
// 创建 channel(类似 Python 的 Queue,但类型安全)
ch := make(chan int)      // 无缓冲(同步)
ch2 := make(chan int, 10) // 有缓冲(异步)

// 发送与接收(<- 操作符)
go func() {
    ch <- 42  // 发送,阻塞直到有人接收
}()

value := <-ch  // 接收,阻塞直到有数据
fmt.Println(value)

// 关闭 channel
close(ch)

// range 遍历 channel(直到关闭)
for v := range ch {
    fmt.Println(v)
}

// select 多路复用(类似 Python select.select)
ch1 := make(chan int)
ch2 := make(chan string)

go func() { ch1 <- 1 }()
go func() { ch2 <- "hi" }()

select {
case v1 := <-ch1:
    fmt.Println("ch1:", v1)
case v2 := <-ch2:
    fmt.Println("ch2:", v2)
case <-time.After(1 * time.Second):  // 超时
    fmt.Println("timeout")
default:  // 非阻塞
    fmt.Println("no data")
}

3. 并发模式示例

Worker Pool(类似 Python 的进程池)

go 复制代码
func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Printf("worker %d processing job %d\n", id, j)
        time.Sleep(time.Second)
        results <- j * 2
    }
}

func main() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)

    // 启动 3 个 worker
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    // 发送 5 个任务
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)

    // 收集结果
    for a := 1; a <= 5; a++ {
        <-results
    }
}

并发安全(sync.Mutex)

go 复制代码
type Counter struct {
    mu    sync.Mutex
    count int
}

func (c *Counter) Inc() {
    c.mu.Lock()
    defer c.mu.Unlock()  // 确保解锁,类似 Python 的 try-finally
    c.count++
}

// 对比 Python:需要 threading.Lock
# lock = threading.Lock()
# with lock:
#     count += 1

4. Context(请求生命周期管理)

go 复制代码
// 带超时的上下文(微服务必备)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

select {
case <-time.Sleep(3 * time.Second):
    fmt.Println("work done")
case <-ctx.Done():
    fmt.Println("timeout:", ctx.Err())  // context deadline exceeded
}

错误处理 {#错误处理}

Go 显式错误处理 vs Python 异常机制。

1. 基本模式

go 复制代码
// 函数返回 (result, error)
func readFile(filename string) ([]byte, error) {
    data, err := os.ReadFile(filename)
    if err != nil {
        return nil, fmt.Errorf("read %s: %w", filename, err)  // 包装错误
    }
    return data, nil
}

// 使用
content, err := readFile("config.json")
if err != nil {
    log.Fatal(err)
}

// 错误链检查(Go 1.13+)
if errors.Is(err, os.ErrNotExist) {
    fmt.Println("file not found")
}

2. 对比 Python

python 复制代码
# Python:try-except 捕获异常
try:
    with open("config.json") as f:
        content = f.read()
except FileNotFoundError:
    print("file not found")
except Exception as e:
    log.error(e)
    raise

Go 哲学:错误是值,不是异常。显式处理每个错误,代码虽冗长但健壮。

3. panic 与 recover(类似异常,但少用)

go 复制代码
// panic 类似 raise,停止当前 goroutine 的调用栈
func mayPanic() {
    panic("something went wrong")
}

// recover 类似 except,只在 defer 中有效
func safeCall() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered:", r)
        }
    }()
    mayPanic()
    fmt.Println("这行不会执行")
}

原则:库代码返回 error,程序级错误才 panic。


标准库常用包 {#标准库常用包}

Go 包 用途 Python 对应
fmt 格式化 I/O print, str.format
os 操作系统接口 os, sys
io/bufio 读写接口 io
net/http HTTP 客户端/服务器 http.client, flask
encoding/json JSON 处理 json
database/sql SQL 数据库接口 sqlite3, SQLAlchemy
time 时间处理 datetime
strings/strconv 字符串/转换 str, int()
sync 并发原语 threading
context 请求上下文 无直接对应

HTTP Server 示例(一行 Python vs Go)

python 复制代码
# Python Flask
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"

# Go 标准库(无需框架)
package main

import (
    "fmt"
    "net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":8080", nil)
}

工程化实践 {#工程化实践}

1. 项目结构(标准布局)

csharp 复制代码
myapp/
├── cmd/                    # 可执行程序入口
│   ├── server/             # 服务1
│   │   └── main.go
│   └── cli/                # 命令行工具
│       └── main.go
├── internal/               # 私有代码(不可被外部导入)
│   ├── auth/               # 认证模块
│   └── db/                 # 数据库
├── pkg/                    # 可复用库代码
│   └── utils/
├── api/                    # API 定义(proto/openapi)
├── web/                    # 静态资源
├── configs/                # 配置文件
├── go.mod
├── go.sum
└── README.md

2. 测试

go 复制代码
// math.go
func Add(a, b int) int {
    return a + b
}

// math_test.go(_test.go 后缀)
package main

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf("Add(2, 3) = %d; want 5", result)
    }
}

// 表驱动测试(Go 惯用模式)
func TestAddTable(t *testing.T) {
    tests := []struct {
        a, b, want int
    }{
        {2, 3, 5},
        {0, 0, 0},
        {-1, 1, 0},
    }
    
    for _, tt := range tests {
        got := Add(tt.a, tt.b)
        if got != tt.want {
            t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, got, tt.want)
        }
    }
}

// 基准测试
func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(1, 2)
    }
}

运行go test -v(详细输出),go test -bench=.(基准测试)

3. 常用工具链

bash 复制代码
go fmt ./...          # 格式化代码(强制风格统一)
go vet ./...          # 静态分析,检查潜在错误
golint ./...          # 风格检查(需安装)
go mod tidy           # 整理依赖

# 性能分析
go test -cpuprofile=cpu.out
go tool pprof cpu.out

从 Python 到 Go 的思维转换 {#思维转换}

Python 思维 Go 思维 转换建议
"写代码要快" "代码要读6个月后的自己" 接受显式错误处理,写注释
"动态类型真方便" "编译器是我最好的朋友" 利用类型安全减少运行时 bug
"继承实现复用" "组合优于继承" 用嵌入结构体 + 接口
"线程/进程处理并发" "goroutine + channel" 忘掉 GIL,拥抱 CSP 模型
"异常处理所有错误" "error 是值,显式处理" 每个错误都检查,不 panic
"pip install 解决一切" "标准库 + 少量依赖" 优先用标准库,谨慎引入第三方
"写脚本快速验证" "写测试快速验证" 养成写单元测试的习惯

学习路线图

  1. 第 1 周:语法基础(变量、控制流、函数、结构体)
  2. 第 2 周:复合类型(slice、map、接口)
  3. 第 3 周:并发编程(goroutine、channel、select)
  4. 第 4 周:标准库实战(HTTP、JSON、数据库)
  5. 第 5-6 周:项目实战(Web 服务、CLI 工具、爬虫)

推荐资源


Go 的设计哲学:简单、显式、组合、并发。作为 Python 开发者,你会失去一些灵活性,但获得编译期安全、极致性能和优雅的并发模型。从写一个小型 HTTP 服务开始,你会爱上这种"less is more"的体验。

相关推荐
秋说1 天前
从局域网到全球访问:GoLand+cpolar 让开发协作无距离
go·内网穿透·goland
HashFlag2 天前
单元测试-gomonkey
单元测试·go·gomonkey
HashFlag3 天前
单元测试-httptest
单元测试·go·httptest
139的世界真奇妙3 天前
工作事宜思考点
经验分享·笔记·golang·go
Grassto3 天前
16 Go Module 常见问题汇总:依赖冲突、版本不生效的原因
golang·go·go module
流浪克拉玛依3 天前
从超卖到原子性:Redis Lua 解决秒杀库存扣减实战
go
怕浪猫4 天前
第16章:标准库精讲(二)net/http、json、time
后端·go·编程语言
下次一定x4 天前
深度解析Kratos服务注册:从框架入口到Consul落地实现
后端·go