./read "从 Python 到 Go(四):面向对..."

从 Python 到 Go(四):面向对象 vs 组合模式

从_python_到_go(四):面向对象_vs_组合模式.md2025-10-15
./meta --show-details
Published
2025年10月15日
Reading
27 min
Words
26,920
Status
PUBLISHED

目录

概述

Python 开发者习惯使用类继承来组织代码,而 Go 采用了完全不同的设计哲学:组合优于继承。Go 没有传统的类和继承,而是通过结构体(struct)、接口(interface)和组合来实现面向对象的特性。

核心差异

特性PythonGo
基本类型classstruct
继承支持多重继承无继承,使用组合
方法定义在类内部定义通过接收者(receiver)关联
接口抽象基类(ABC)隐式接口(duck typing)
多态通过继承和方法重写通过接口实现
封装约定(_前缀)大小写控制可见性

类与结构体对比

Python 的类

# Python - 类定义
class Person:
    """人员类"""

    def __init__(self, name, age):
        self.name = name        # 公有属性
        self._age = age         # 约定的私有属性
        self.__secret = "xxx"   # 名称混淆的私有属性

    def greet(self):
        return f"Hello, I'm {self.name}"

    def get_age(self):
        return self._age

    @property
    def adult(self):
        return self._age >= 18

    @staticmethod
    def species():
        return "Homo sapiens"

    @classmethod
    def from_birth_year(cls, name, birth_year):
        age = 2025 - birth_year
        return cls(name, age)

# 使用
person = Person("Alice", 30)
print(person.greet())           # Hello, I'm Alice
print(person.adult)             # True
print(Person.species())         # Homo sapiens
person2 = Person.from_birth_year("Bob", 1990)

Go 的结构体

// Go - 结构体定义
package main

import "fmt"

// Person 结构体(首字母大写表示公开)
type Person struct {
    Name   string  // 公开字段
    age    int     // 私有字段(小写开头)
    secret string  // 私有字段
}

// 构造函数(约定命名为 NewXxx)
func NewPerson(name string, age int) *Person {
    return &Person{
        Name:   name,
        age:    age,
        secret: "xxx",
    }
}

// 方法 - 值接收者
func (p Person) Greet() string {
    return fmt.Sprintf("Hello, I'm %s", p.Name)
}

// 方法 - 指针接收者(可修改对象)
func (p *Person) SetAge(age int) {
    p.age = age
}

// Getter 方法
func (p Person) GetAge() int {
    return p.age
}

// 计算属性通过方法实现
func (p Person) IsAdult() bool {
    return p.age >= 18
}

// 静态方法模拟(包级函数)
func Species() string {
    return "Homo sapiens"
}

// 工厂方法
func FromBirthYear(name string, birthYear int) *Person {
    age := 2025 - birthYear
    return NewPerson(name, age)
}

func main() {
    person := NewPerson("Alice", 30)
    fmt.Println(person.Greet())      // Hello, I'm Alice
    fmt.Println(person.IsAdult())    // true
    fmt.Println(Species())           // Homo sapiens

    person2 := FromBirthYear("Bob", 1990)
    fmt.Printf("%+v\n", person2)
}

关键差异说明

概念PythonGo
构造函数init 魔术方法约定使用 NewXxx 函数
self 参数显式的第一个参数接收者(receiver)在函数名前
访问控制约定(_前缀)和名称混淆首字母大小写决定可见性
属性装饰器@property通过方法显式调用
类方法@classmethod包级函数
静态方法@staticmethod包级函数

继承 vs 组合

Python 的继承

# Python - 传统继承方式
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("子类必须实现")

    def move(self):
        return f"{self.name} is moving"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed

    def speak(self):
        return f"{self.name} says Woof!"

    def fetch(self):
        return f"{self.name} fetches the ball"

class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name)
        self.color = color

    def speak(self):
        return f"{self.name} says Meow!"

    def climb(self):
        return f"{self.name} climbs the tree"

# 使用
dog = Dog("Buddy", "Golden Retriever")
print(dog.speak())    # Buddy says Woof!
print(dog.move())     # Buddy is moving
print(dog.fetch())    # Buddy fetches the ball

cat = Cat("Whiskers", "Orange")
print(cat.speak())    # Whiskers says Meow!
print(cat.climb())    # Whiskers climbs the tree

Go 的组合(Embedding)

// Go - 使用组合和嵌入
package main

import "fmt"

// 基础类型
type Animal struct {
    Name string
}

// Animal 的方法
func (a Animal) Move() string {
    return fmt.Sprintf("%s is moving", a.Name)
}

// Dog 通过嵌入 Animal 获得其字段和方法
type Dog struct {
    Animal  // 匿名嵌入(embedding)
    Breed string
}

// Dog 特有的方法
func (d Dog) Speak() string {
    return fmt.Sprintf("%s says Woof!", d.Name)
}

func (d Dog) Fetch() string {
    return fmt.Sprintf("%s fetches the ball", d.Name)
}

// Cat 同样嵌入 Animal
type Cat struct {
    Animal
    Color string
}

func (c Cat) Speak() string {
    return fmt.Sprintf("%s says Meow!", c.Name)
}

func (c Cat) Climb() string {
    return fmt.Sprintf("%s climbs the tree", c.Name)
}

func main() {
    dog := Dog{
        Animal: Animal{Name: "Buddy"},
        Breed:  "Golden Retriever",
    }
    fmt.Println(dog.Speak())  // Buddy says Woof!
    fmt.Println(dog.Move())   // Buddy is moving (继承自 Animal)
    fmt.Println(dog.Fetch())  // Buddy fetches the ball

    cat := Cat{
        Animal: Animal{Name: "Whiskers"},
        Color:  "Orange",
    }
    fmt.Println(cat.Speak())  // Whiskers says Meow!
    fmt.Println(cat.Climb())  // Whiskers climbs the tree

    // 直接访问嵌入字段的属性(提升)
    fmt.Println(dog.Name)     // Buddy (不需要 dog.Animal.Name)
}

组合的灵活性

Go 的组合比 Python 的继承更灵活,因为可以嵌入多个类型:

// Go - 多重组合
package main

import "fmt"

// 可以嵌入多个类型
type Swimmer struct{}

func (s Swimmer) Swim() string {
    return "Swimming in water"
}

type Flyer struct{}

func (f Flyer) Fly() string {
    return "Flying in the sky"
}

// Duck 同时具有游泳和飞行能力
type Duck struct {
    Animal
    Swimmer
    Flyer
}

func (d Duck) Speak() string {
    return fmt.Sprintf("%s says Quack!", d.Name)
}

func main() {
    duck := Duck{
        Animal: Animal{Name: "Donald"},
    }

    fmt.Println(duck.Speak())  // Donald says Quack!
    fmt.Println(duck.Swim())   // Swimming in water
    fmt.Println(duck.Fly())    // Flying in the sky
    fmt.Println(duck.Move())   // Donald is moving
}

Python 的多重继承对比:

# Python - 多重继承(可能导致 MRO 问题)
class Swimmer:
    def swim(self):
        return "Swimming in water"

class Flyer:
    def fly(self):
        return "Flying in the sky"

class Duck(Animal, Swimmer, Flyer):
    def __init__(self, name):
        super().__init__(name)

    def speak(self):
        return f"{self.name} says Quack!"

duck = Duck("Donald")
print(duck.speak())  # Donald says Quack!
print(duck.swim())   # Swimming in water
print(duck.fly())    # Flying in the sky

方法与接收者

值接收者 vs 指针接收者

这是 Go 特有的概念,Python 中所有方法都隐式使用引用。

// Go - 接收者类型对比
package main

import "fmt"

type Counter struct {
    count int
}

// 值接收者 - 接收副本,不能修改原对象
func (c Counter) GetCount() int {
    return c.count
}

// 值接收者尝试修改(无效)
func (c Counter) IncrementWrong() {
    c.count++  // 只修改了副本!
}

// 指针接收者 - 可以修改原对象
func (c *Counter) Increment() {
    c.count++
}

// 指针接收者 - 避免大对象拷贝
type LargeStruct struct {
    data [1000000]int
}

func (l *LargeStruct) Process() {
    // 使用指针避免拷贝 100 万个整数
}

func main() {
    counter := Counter{count: 0}

    fmt.Println(counter.GetCount())  // 0

    counter.IncrementWrong()
    fmt.Println(counter.GetCount())  // 0 (没有变化!)

    counter.Increment()
    fmt.Println(counter.GetCount())  // 1 (成功修改)

    // Go 会自动处理指针解引用
    counterPtr := &Counter{count: 10}
    counterPtr.Increment()           // 自动:(*counterPtr).Increment()
    fmt.Println(counterPtr.count)    // 11
}

Python 对比:

# Python - 所有对象都是引用
class Counter:
    def __init__(self, count=0):
        self.count = count

    def get_count(self):
        return self.count

    def increment(self):
        self.count += 1  # 总是修改原对象

counter = Counter()
print(counter.get_count())  # 0
counter.increment()
print(counter.get_count())  # 1

选择接收者类型的规则

场景使用值接收者使用指针接收者
需要修改接收者
接收者是大型结构体❌ (拷贝开销大)
接收者是小型结构体(几个字段)可选
接收者包含 sync.Mutex 等同步原语❌ (不能拷贝)
需要一致性(同类型方法应使用相同接收者)保持一致

接口与鸭子类型

Python 的抽象基类

# Python - 使用 ABC 定义接口
from abc import ABC, abstractmethod

class Speaker(ABC):
    """说话者接口"""

    @abstractmethod
    def speak(self):
        pass

    @abstractmethod
    def volume(self):
        pass

class Person(Speaker):
    def __init__(self, name):
        self.name = name

    def speak(self):
        return f"Hello, I'm {self.name}"

    def volume(self):
        return 50

class Robot(Speaker):
    def __init__(self, model):
        self.model = model

    def speak(self):
        return f"Robot {self.model} online"

    def volume(self):
        return 80

# 多态使用
def make_speak(speaker: Speaker):
    print(f"{speaker.speak()} (Volume: {speaker.volume()})")

person = Person("Alice")
robot = Robot("T-800")

make_speak(person)  # Hello, I'm Alice (Volume: 50)
make_speak(robot)   # Robot T-800 online (Volume: 80)

Go 的隐式接口

// Go - 接口是隐式实现的
package main

import "fmt"

// 定义接口
type Speaker interface {
    Speak() string
    Volume() int
}

// Person 实现了 Speaker 接口(隐式)
type Person struct {
    Name string
}

func (p Person) Speak() string {
    return fmt.Sprintf("Hello, I'm %s", p.Name)
}

func (p Person) Volume() int {
    return 50
}

// Robot 也实现了 Speaker 接口
type Robot struct {
    Model string
}

func (r Robot) Speak() string {
    return fmt.Sprintf("Robot %s online", r.Model)
}

func (r Robot) Volume() int {
    return 80
}

// 多态函数
func MakeSpeak(s Speaker) {
    fmt.Printf("%s (Volume: %d)\n", s.Speak(), s.Volume())
}

func main() {
    person := Person{Name: "Alice"}
    robot := Robot{Model: "T-800"}

    MakeSpeak(person)  // Hello, I'm Alice (Volume: 50)
    MakeSpeak(robot)   // Robot T-800 online (Volume: 80)

    // 接口值可以存储任何实现了该接口的类型
    var speakers []Speaker
    speakers = append(speakers, person, robot)

    for _, speaker := range speakers {
        MakeSpeak(speaker)
    }
}

接口的核心优势

特性Python (ABC)Go Interface
实现方式显式继承隐式实现(鸭子类型)
解耦程度接口和实现耦合完全解耦
第三方类型无法让第三方类型实现接口可以为任何类型定义接口
接口组合多重继承接口嵌入
空接口无对应概念interface 可以接受任何类型

接口组合

// Go - 接口组合
package main

import "fmt"

// 小接口
type Reader interface {
    Read() string
}

type Writer interface {
    Write(data string) error
}

type Closer interface {
    Close() error
}

// 组合接口
type ReadWriter interface {
    Reader
    Writer
}

type ReadWriteCloser interface {
    Reader
    Writer
    Closer
}

// 实现
type File struct {
    name string
    data string
}

func (f *File) Read() string {
    return f.data
}

func (f *File) Write(data string) error {
    f.data += data
    return nil
}

func (f *File) Close() error {
    fmt.Printf("Closing file %s\n", f.name)
    return nil
}

// 函数只需要用到的接口
func Copy(reader Reader, writer Writer) error {
    data := reader.Read()
    return writer.Write(data)
}

func main() {
    file := &File{name: "test.txt", data: "Hello"}

    // file 实现了所有三个接口
    var r Reader = file
    var w Writer = file
    var rw ReadWriter = file
    var rwc ReadWriteCloser = file

    fmt.Println(r.Read())
    w.Write(" World")
    Copy(r, w)
    rwc.Close()
}

实战案例

案例 1:插件系统

Python 版本:

# Python - 插件系统
from abc import ABC, abstractmethod
from typing import List

class Plugin(ABC):
    """插件接口"""

    @abstractmethod
    def name(self) -> str:
        pass

    @abstractmethod
    def execute(self, data: dict) -> dict:
        pass

class LoggerPlugin(Plugin):
    def name(self) -> str:
        return "Logger"

    def execute(self, data: dict) -> dict:
        print(f"[LOG] Processing: {data}")
        return data

class ValidatorPlugin(Plugin):
    def name(self) -> str:
        return "Validator"

    def execute(self, data: dict) -> dict:
        if "user_id" not in data:
            raise ValueError("Missing user_id")
        print(f"[VALIDATE] Data valid: {data}")
        return data

class TransformPlugin(Plugin):
    def name(self) -> str:
        return "Transform"

    def execute(self, data: dict) -> dict:
        data["processed"] = True
        print(f"[TRANSFORM] Data transformed: {data}")
        return data

class PluginManager:
    def __init__(self):
        self.plugins: List[Plugin] = []

    def register(self, plugin: Plugin):
        self.plugins.append(plugin)
        print(f"Registered plugin: {plugin.name()}")

    def process(self, data: dict) -> dict:
        result = data
        for plugin in self.plugins:
            result = plugin.execute(result)
        return result

# 使用
manager = PluginManager()
manager.register(LoggerPlugin())
manager.register(ValidatorPlugin())
manager.register(TransformPlugin())

result = manager.process({"user_id": 123, "action": "login"})
print(f"Final result: {result}")

Go 版本:

// Go - 插件系统
package main

import (
    "errors"
    "fmt"
)

// Plugin 接口
type Plugin interface {
    Name() string
    Execute(data map[string]interface{}) (map[string]interface{}, error)
}

// LoggerPlugin 实现
type LoggerPlugin struct{}

func (l LoggerPlugin) Name() string {
    return "Logger"
}

func (l LoggerPlugin) Execute(data map[string]interface{}) (map[string]interface{}, error) {
    fmt.Printf("[LOG] Processing: %v\n", data)
    return data, nil
}

// ValidatorPlugin 实现
type ValidatorPlugin struct{}

func (v ValidatorPlugin) Name() string {
    return "Validator"
}

func (v ValidatorPlugin) Execute(data map[string]interface{}) (map[string]interface{}, error) {
    if _, ok := data["user_id"]; !ok {
        return nil, errors.New("missing user_id")
    }
    fmt.Printf("[VALIDATE] Data valid: %v\n", data)
    return data, nil
}

// TransformPlugin 实现
type TransformPlugin struct{}

func (t TransformPlugin) Name() string {
    return "Transform"
}

func (t TransformPlugin) Execute(data map[string]interface{}) (map[string]interface{}, error) {
    data["processed"] = true
    fmt.Printf("[TRANSFORM] Data transformed: %v\n", data)
    return data, nil
}

// PluginManager 管理器
type PluginManager struct {
    plugins []Plugin
}

func NewPluginManager() *PluginManager {
    return &PluginManager{
        plugins: make([]Plugin, 0),
    }
}

func (pm *PluginManager) Register(plugin Plugin) {
    pm.plugins = append(pm.plugins, plugin)
    fmt.Printf("Registered plugin: %s\n", plugin.Name())
}

func (pm *PluginManager) Process(data map[string]interface{}) (map[string]interface{}, error) {
    result := data
    var err error

    for _, plugin := range pm.plugins {
        result, err = plugin.Execute(result)
        if err != nil {
            return nil, fmt.Errorf("plugin %s failed: %w", plugin.Name(), err)
        }
    }

    return result, nil
}

func main() {
    manager := NewPluginManager()
    manager.Register(LoggerPlugin{})
    manager.Register(ValidatorPlugin{})
    manager.Register(TransformPlugin{})

    data := map[string]interface{}{
        "user_id": 123,
        "action":  "login",
    }

    result, err := manager.Process(data)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    fmt.Printf("Final result: %v\n", result)
}

案例 2:装饰器模式

Python 版本(使用继承):

# Python - 装饰器模式
class Coffee:
    def cost(self) -> float:
        return 2.0

    def description(self) -> str:
        return "Coffee"

class CoffeeDecorator(Coffee):
    def __init__(self, coffee: Coffee):
        self._coffee = coffee

    def cost(self) -> float:
        return self._coffee.cost()

    def description(self) -> str:
        return self._coffee.description()

class Milk(CoffeeDecorator):
    def cost(self) -> float:
        return self._coffee.cost() + 0.5

    def description(self) -> str:
        return self._coffee.description() + ", Milk"

class Sugar(CoffeeDecorator):
    def cost(self) -> float:
        return self._coffee.cost() + 0.2

    def description(self) -> str:
        return self._coffee.description() + ", Sugar"

class Vanilla(CoffeeDecorator):
    def cost(self) -> float:
        return self._coffee.cost() + 0.8

    def description(self) -> str:
        return self._coffee.description() + ", Vanilla"

# 使用
coffee = Coffee()
print(f"{coffee.description()}: ${coffee.cost()}")  # Coffee: $2.0

coffee_with_milk = Milk(coffee)
print(f"{coffee_with_milk.description()}: ${coffee_with_milk.cost()}")
# Coffee, Milk: $2.5

fancy_coffee = Vanilla(Sugar(Milk(Coffee())))
print(f"{fancy_coffee.description()}: ${fancy_coffee.cost()}")
# Coffee, Milk, Sugar, Vanilla: $3.5

Go 版本(使用组合和接口):

// Go - 装饰器模式
package main

import "fmt"

// Beverage 接口
type Beverage interface {
    Cost() float64
    Description() string
}

// Coffee 基础实现
type Coffee struct{}

func (c Coffee) Cost() float64 {
    return 2.0
}

func (c Coffee) Description() string {
    return "Coffee"
}

// Milk 装饰器
type Milk struct {
    beverage Beverage
}

func NewMilk(b Beverage) Beverage {
    return Milk{beverage: b}
}

func (m Milk) Cost() float64 {
    return m.beverage.Cost() + 0.5
}

func (m Milk) Description() string {
    return m.beverage.Description() + ", Milk"
}

// Sugar 装饰器
type Sugar struct {
    beverage Beverage
}

func NewSugar(b Beverage) Beverage {
    return Sugar{beverage: b}
}

func (s Sugar) Cost() float64 {
    return s.beverage.Cost() + 0.2
}

func (s Sugar) Description() string {
    return s.beverage.Description() + ", Sugar"
}

// Vanilla 装饰器
type Vanilla struct {
    beverage Beverage
}

func NewVanilla(b Beverage) Beverage {
    return Vanilla{beverage: b}
}

func (v Vanilla) Cost() float64 {
    return v.beverage.Cost() + 0.8
}

func (v Vanilla) Description() string {
    return v.beverage.Description() + ", Vanilla"
}

// 辅助函数打印饮料信息
func PrintBeverage(b Beverage) {
    fmt.Printf("%s: $%.1f\n", b.Description(), b.Cost())
}

func main() {
    coffee := Coffee{}
    PrintBeverage(coffee)  // Coffee: $2.0

    coffeeWithMilk := NewMilk(coffee)
    PrintBeverage(coffeeWithMilk)  // Coffee, Milk: $2.5

    fancyCoffee := NewVanilla(NewSugar(NewMilk(Coffee{})))
    PrintBeverage(fancyCoffee)  // Coffee, Milk, Sugar, Vanilla: $3.5
}

案例 3:策略模式

Python 版本:

# Python - 策略模式
from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: float) -> str:
        pass

class CreditCardPayment(PaymentStrategy):
    def __init__(self, card_number: str):
        self.card_number = card_number

    def pay(self, amount: float) -> str:
        return f"Paid ${amount} with credit card {self.card_number}"

class PayPalPayment(PaymentStrategy):
    def __init__(self, email: str):
        self.email = email

    def pay(self, amount: float) -> str:
        return f"Paid ${amount} via PayPal ({self.email})"

class CryptoPayment(PaymentStrategy):
    def __init__(self, wallet_address: str):
        self.wallet_address = wallet_address

    def pay(self, amount: float) -> str:
        return f"Paid ${amount} with crypto to {self.wallet_address}"

class ShoppingCart:
    def __init__(self):
        self.items = []
        self.payment_strategy = None

    def add_item(self, item: str, price: float):
        self.items.append({"item": item, "price": price})

    def set_payment_strategy(self, strategy: PaymentStrategy):
        self.payment_strategy = strategy

    def checkout(self) -> str:
        total = sum(item["price"] for item in self.items)
        if not self.payment_strategy:
            return "No payment method selected"
        return self.payment_strategy.pay(total)

# 使用
cart = ShoppingCart()
cart.add_item("Laptop", 999.99)
cart.add_item("Mouse", 29.99)

# 用信用卡支付
cart.set_payment_strategy(CreditCardPayment("1234-5678-9012-3456"))
print(cart.checkout())

# 换成 PayPal 支付
cart.set_payment_strategy(PayPalPayment("[email protected]"))
print(cart.checkout())

Go 版本:

// Go - 策略模式
package main

import "fmt"

// PaymentStrategy 接口
type PaymentStrategy interface {
    Pay(amount float64) string
}

// CreditCardPayment 实现
type CreditCardPayment struct {
    CardNumber string
}

func (c CreditCardPayment) Pay(amount float64) string {
    return fmt.Sprintf("Paid $%.2f with credit card %s", amount, c.CardNumber)
}

// PayPalPayment 实现
type PayPalPayment struct {
    Email string
}

func (p PayPalPayment) Pay(amount float64) string {
    return fmt.Sprintf("Paid $%.2f via PayPal (%s)", amount, p.Email)
}

// CryptoPayment 实现
type CryptoPayment struct {
    WalletAddress string
}

func (c CryptoPayment) Pay(amount float64) string {
    return fmt.Sprintf("Paid $%.2f with crypto to %s", amount, c.WalletAddress)
}

// Item 商品
type Item struct {
    Name  string
    Price float64
}

// ShoppingCart 购物车
type ShoppingCart struct {
    items           []Item
    paymentStrategy PaymentStrategy
}

func NewShoppingCart() *ShoppingCart {
    return &ShoppingCart{
        items: make([]Item, 0),
    }
}

func (sc *ShoppingCart) AddItem(name string, price float64) {
    sc.items = append(sc.items, Item{Name: name, Price: price})
}

func (sc *ShoppingCart) SetPaymentStrategy(strategy PaymentStrategy) {
    sc.paymentStrategy = strategy
}

func (sc *ShoppingCart) Checkout() string {
    var total float64
    for _, item := range sc.items {
        total += item.Price
    }

    if sc.paymentStrategy == nil {
        return "No payment method selected"
    }

    return sc.paymentStrategy.Pay(total)
}

func main() {
    cart := NewShoppingCart()
    cart.AddItem("Laptop", 999.99)
    cart.AddItem("Mouse", 29.99)

    // 用信用卡支付
    cart.SetPaymentStrategy(CreditCardPayment{CardNumber: "1234-5678-9012-3456"})
    fmt.Println(cart.Checkout())

    // 换成 PayPal 支付
    cart.SetPaymentStrategy(PayPalPayment{Email: "[email protected]"})
    fmt.Println(cart.Checkout())

    // 加密货币支付
    cart.SetPaymentStrategy(CryptoPayment{WalletAddress: "0x1234abcd"})
    fmt.Println(cart.Checkout())
}

最佳实践

1. 优先使用小接口

// ❌ 不好:大接口
type Database interface {
    Connect() error
    Disconnect() error
    Query(sql string) ([]Row, error)
    Insert(table string, data map[string]interface{}) error
    Update(table string, id int, data map[string]interface{}) error
    Delete(table string, id int) error
    BeginTransaction() error
    CommitTransaction() error
    RollbackTransaction() error
}

// ✅ 好:小接口组合
type Connector interface {
    Connect() error
    Disconnect() error
}

type Querier interface {
    Query(sql string) ([]Row, error)
}

type Writer interface {
    Insert(table string, data map[string]interface{}) error
    Update(table string, id int, data map[string]interface{}) error
    Delete(table string, id int) error
}

type Transactioner interface {
    BeginTransaction() error
    CommitTransaction() error
    RollbackTransaction() error
}

// 根据需要组合
type Database interface {
    Connector
    Querier
    Writer
    Transactioner
}

2. 接受接口,返回具体类型

// ✅ 好的设计
func ProcessData(r io.Reader) *Result {
    // 接受接口,灵活性高
    data, _ := io.ReadAll(r)
    return &Result{Data: data}  // 返回具体类型
}

// ❌ 不好:返回接口
func ProcessDataBad(r io.Reader) io.Reader {
    // 返回接口限制了实现细节
    return bytes.NewReader([]byte{})
}

3. 使用组合而非继承

// ✅ 好:组合
type Logger struct {
    writer io.Writer
}

func (l *Logger) Log(msg string) {
    l.writer.Write([]byte(msg))
}

type App struct {
    logger Logger
    config Config
}

// ❌ Python 式继承思维(Go 中不推荐)
type BaseApp struct {
    // 基础功能
}

type WebApp struct {
    BaseApp  // 这样用组合模拟继承不是 Go 的惯用法
}

4. 为接收者选择一致的类型

// ✅ 好:统一使用指针接收者
type User struct {
    name string
    age  int
}

func (u *User) GetName() string {
    return u.name
}

func (u *User) SetName(name string) {
    u.name = name
}

func (u *User) GetAge() int {
    return u.age
}

// ❌ 不好:混用值和指针接收者
func (u User) GetNameBad() string {  // 值接收者
    return u.name
}

func (u *User) SetNameBad(name string) {  // 指针接收者
    u.name = name
}

5. 接口在使用处定义

// ✅ 好:消费者定义接口
// package consumer
type DataReader interface {
    Read() ([]byte, error)
}

func ProcessData(reader DataReader) {
    // 使用接口
}

// package provider
type FileReader struct{}

func (f FileReader) Read() ([]byte, error) {
    // 实现,无需知道接口定义
    return nil, nil
}

// ❌ Python 式思维:在提供者处定义接口
// 这在 Go 中不是最佳实践

总结

Python 到 Go 的思维转变

Python 思维Go 思维
类是核心抽象接口是核心抽象
继承复用代码组合复用代码
显式实现接口隐式满足接口
大而全的类小而专的类型
方法在类内部方法通过接收者关联
使用 @property 装饰器使用显式 getter/setter 方法

关键要点

  1. 放弃继承思维:Go 没有继承,使用组合和接口实现代码复用
  2. 小接口原则:定义小而专的接口,而不是大而全的抽象类
  3. 隐式实现:类型无需声明实现了哪个接口,只要方法匹配即可
  4. 接收者类型:理解值接收者和指针接收者的区别,根据需要选择
  5. 组合优于继承:通过嵌入和组合实现代码复用,而不是继承层次
  6. 接口在使用处定义:由使用者定义需要的接口,而不是提供者

实用建议

  • 🔧 从 Python 类转换时,先考虑是否真的需要方法,很多时候函数就够了
  • 🔧 不要试图在 Go 中复刻 Python 的类层次结构
  • 🔧 优先使用接口进行抽象,而不是具体类型
  • 🔧 保持接口小而专,遵循单一职责原则
  • 🔧 使用组合而非嵌入来表达"有一个"关系
  • 🔧 接收者类型选择要一致,不要在同一类型上混用

下一篇错误处理:从异常到 error

上一篇数据结构与集合操作

系列目录从 Python 到 Go 完全指南

comments.logDiscussion Thread
./comments --show-all

讨论区

./loading comments...