2.5【方法接口】Go 方法实现与接口设计
2.5【方法接口】Go 方法实现与接口设计
目录
Go 方法基础
1. 方法的概念与语法
方法与函数的区别
// 函数:独立的代码块
func calculateArea(length, width float64) float64 {
return length * width
}
// 方法:与特定类型关联的函数
type Rectangle struct {
Length float64
Width float64
}
// 方法:属于 Rectangle 类型
func (r Rectangle) CalculateArea() float64 {
return r.Length * r.Width
}
// 使用示例
func main() {
rect := Rectangle{Length: 5, Width: 3}
// 调用函数
area1 := calculateArea(5, 3)
// 调用方法
area2 := rect.CalculateArea()
fmt.Printf("函数结果: %.2f\n", area1) // 15.00
fmt.Printf("方法结果: %.2f\n", area2) // 15.00
}
方法语法结构
// 方法的完整语法结构
func (receiver ReceiverType) MethodName(parameters) (returnTypes) {
// 方法体
return values
}
// 组成部分说明:
// - receiver: 接收者,方法所属的类型实例
// - ReceiverType: 接收者类型
// - MethodName: 方法名
// - parameters: 参数列表
// - returnTypes: 返回值类型
2. 为不同类型定义方法
为结构体类型定义方法
type Person struct {
Name string
Age int
}
// 基本方法
func (p Person) GetInfo() string {
return fmt.Sprintf("姓名: %s, 年龄: %d", p.Name, p.Age)
}
// 带参数的方法
func (p Person) Greet(greeting string) string {
return fmt.Sprintf("%s, 我是 %s", greeting, p.Name)
}
// 多返回值方法
func (p Person) IsAdult() (bool, string) {
if p.Age >= 18 {
return true, "成年人"
}
return false, "未成年人"
}
// 使用示例
func structMethodExample() {
person := Person{Name: "张三", Age: 25}
fmt.Println(person.GetInfo()) // 姓名: 张三, 年龄: 25
fmt.Println(person.Greet("你好")) // 你好, 我是 张三
isAdult, status := person.IsAdult()
fmt.Printf("成年状态: %v (%s)\n", isAdult, status) // 成年状态: true (成年人)
}
为基本类型定义方法
// 为自定义的基本类型定义方法
type MyInt int
func (m MyInt) IsEven() bool {
return int(m)%2 == 0
}
func (m MyInt) Double() MyInt {
return m * 2
}
func (m MyInt) String() string {
return fmt.Sprintf("MyInt(%d)", m)
}
// 为字符串类型定义方法
type MyString string
func (s MyString) Reverse() MyString {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return MyString(runes)
}
func (s MyString) WordCount() int {
return len(strings.Fields(string(s)))
}
// 使用示例
func basicTypeMethodExample() {
num := MyInt(42)
fmt.Printf("%s 是偶数: %v\n", num.String(), num.IsEven()) // MyInt(42) 是偶数: true
fmt.Printf("双倍值: %s\n", num.Double().String()) // 双倍值: MyInt(84)
text := MyString("hello world 你好世界")
fmt.Printf("原文: %s\n", text) // 原文: hello world 你好世界
fmt.Printf("反转: %s\n", text.Reverse()) // 反转: 界世好你 dlrow olleh
fmt.Printf("单词数: %d\n", text.WordCount()) // 单词数: 4
}
为切片类型定义方法
type IntSlice []int
// 查找元素
func (s IntSlice) Contains(value int) bool {
for _, v := range s {
if v == value {
return true
}
}
return false
}
// 求和
func (s IntSlice) Sum() int {
sum := 0
for _, v := range s {
sum += v
}
return sum
}
// 求平均值
func (s IntSlice) Average() float64 {
if len(s) == 0 {
return 0
}
return float64(s.Sum()) / float64(len(s))
}
// 查找最大值
func (s IntSlice) Max() (int, error) {
if len(s) == 0 {
return 0, fmt.Errorf("空切片没有最大值")
}
max := s[0]
for _, v := range s[1:] {
if v > max {
max = v
}
}
return max, nil
}
// 使用示例
func sliceMethodExample() {
numbers := IntSlice{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Printf("包含 5: %v\n", numbers.Contains(5)) // true
fmt.Printf("包含 15: %v\n", numbers.Contains(15)) // false
fmt.Printf("总和: %d\n", numbers.Sum()) // 55
fmt.Printf("平均值: %.2f\n", numbers.Average()) // 5.50
max, err := numbers.Max()
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Printf("最大值: %d\n", max) // 10
}
}
接收者类型详解
1. 值接收者 vs 指针接收者
值接收者(Value Receiver)
type Counter struct {
Value int
}
// 值接收者 - 接收类型的副本
func (c Counter) GetValue() int {
return c.Value
}
// 值接收者 - 无法修改原始值
func (c Counter) IncrementValue() {
c.Value++ // 只修改副本,不影响原始值
}
func valueReceiverExample() {
counter := Counter{Value: 10}
fmt.Printf("初始值: %d\n", counter.GetValue()) // 初始值: 10
counter.IncrementValue() // 尝试增加值
fmt.Printf("调用后值: %d\n", counter.GetValue()) // 调用后值: 10 (未改变)
}
指针接收者(Pointer Receiver)
// 指针接收者 - 接收类型的指针
func (c *Counter) GetValuePtr() int {
return c.Value
}
// 指针接收者 - 可以修改原始值
func (c *Counter) IncrementPtr() {
c.Value++ // 修改原始值
}
// 指针接收者 - 重置方法
func (c *Counter) Reset() {
c.Value = 0
}
func pointerReceiverExample() {
counter := Counter{Value: 10}
fmt.Printf("初始值: %d\n", counter.GetValuePtr()) // 初始值: 10
counter.IncrementPtr() // 增加值
fmt.Printf("增加后: %d\n", counter.GetValuePtr()) // 增加后: 11
counter.Reset() // 重置
fmt.Printf("重置后: %d\n", counter.GetValuePtr()) // 重置后: 0
}
混合使用值接收者和指针接收者
type BankAccount struct {
Balance float64
Owner string
}
// 值接收者 - 用于读取操作(不修改状态)
func (b BankAccount) GetBalance() float64 {
return b.Balance
}
func (b BankAccount) GetOwner() string {
return b.Owner
}
func (b BankAccount) GetInfo() string {
return fmt.Sprintf("账户所有者: %s, 余额: ¥%.2f", b.Owner, b.Balance)
}
// 指针接收者 - 用于修改操作
func (b *BankAccount) Deposit(amount float64) error {
if amount <= 0 {
return fmt.Errorf("存款金额必须大于 0")
}
b.Balance += amount
return nil
}
func (b *BankAccount) Withdraw(amount float64) error {
if amount <= 0 {
return fmt.Errorf("取款金额必须大于 0")
}
if amount > b.Balance {
return fmt.Errorf("余额不足")
}
b.Balance -= amount
return nil
}
func (b *BankAccount) Transfer(to *BankAccount, amount float64) error {
if err := b.Withdraw(amount); err != nil {
return fmt.Errorf("转账失败: %v", err)
}
if err := to.Deposit(amount); err != nil {
// 如果存款失败,需要回滚
b.Balance += amount
return fmt.Errorf("转账失败: %v", err)
}
return nil
}
// 使用示例
func bankAccountExample() {
account1 := BankAccount{Balance: 1000, Owner: "张三"}
account2 := BankAccount{Balance: 500, Owner: "李四"}
fmt.Println(account1.GetInfo()) // 账户所有者: 张三, 余额: ¥1000.00
fmt.Println(account2.GetInfo()) // 账户所有者: 李四, 余额: ¥500.00
// 存款
err := account1.Deposit(200)
if err != nil {
fmt.Printf("存款失败: %v\n", err)
} else {
fmt.Printf("存款后 %s\n", account1.GetInfo()) // 账户所有者: 张三, 余额: ¥1200.00
}
// 转账
err = account1.Transfer(&account2, 300)
if err != nil {
fmt.Printf("转账失败: %v\n", err)
} else {
fmt.Printf("转账后 %s\n", account1.GetInfo()) // 账户所有者: 张三, 余额: ¥900.00
fmt.Printf("转账后 %s\n", account2.GetInfo()) // 账户所有者: 李四, 余额: ¥800.00
}
}
2. 选择接收者类型的原则
何时使用指针接收者
// 1. 需要修改接收者的状态
type Timer struct {
seconds int
}
func (t *Timer) Start() {
t.seconds = 0 // 修改状态
}
func (t *Timer) Tick() {
t.seconds++ // 修改状态
}
// 2. 接收者是大型结构体(避免复制开销)
type LargeStruct struct {
data [10000]int
name string
}
func (l *LargeStruct) ProcessData() {
// 使用指针避免复制大量数据
for i := range l.data {
l.data[i] = i * 2
}
}
// 3. 需要实现接口,且接口的其他方法使用指针接收者
type Drawable interface {
Draw()
Move(x, y int)
}
type Circle struct {
x, y int
radius int
}
func (c *Circle) Draw() {
fmt.Printf("在 (%d, %d) 画半径为 %d 的圆\n", c.x, c.y, c.radius)
}
func (c *Circle) Move(x, y int) {
c.x = x // 需要修改位置
c.y = y
}
何时使用值接收者
// 1. 方法不修改接收者状态
type Point struct {
X, Y float64
}
func (p Point) Distance() float64 {
return math.Sqrt(p.X*p.X + p.Y*p.Y) // 只读操作
}
func (p Point) String() string {
return fmt.Sprintf("(%.2f, %.2f)", p.X, p.Y) // 只读操作
}
// 2. 接收者是小型值类型
type Temperature int
func (t Temperature) Celsius() float64 {
return float64(t)
}
func (t Temperature) Fahrenheit() float64 {
return float64(t)*9/5 + 32
}
// 3. 需要接收者的副本进行操作
type Money int
func (m Money) Add(other Money) Money {
return m + other // 返回新值,不修改原值
}
func (m Money) Multiply(factor int) Money {
return m * Money(factor) // 返回新值,不修改原值
}
接口定义与实现
1. 接口基础概念
接口的定义与语法
// 接口定义语法
type InterfaceName interface {
Method1(parameters) returnTypes
Method2(parameters) returnTypes
// ... 更多方法
}
// 示例:几何图形接口
type Shape interface {
Area() float64 // 计算面积
Perimeter() float64 // 计算周长
}
// 可移动接口
type Movable interface {
Move(dx, dy float64) // 移动
GetPosition() (float64, float64) // 获取位置
}
// 组合接口
type MovableShape interface {
Shape // 嵌入 Shape 接口
Movable // 嵌入 Movable 接口
}
接口的隐式实现
// Go 中不需要显式声明实现接口,只要类型实现了接口的所有方法即可
type Rectangle struct {
Width, Height float64
X, Y float64
}
// 实现 Shape 接口的方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// 实现 Movable 接口的方法
func (r *Rectangle) Move(dx, dy float64) {
r.X += dx
r.Y += dy
}
func (r Rectangle) GetPosition() (float64, float64) {
return r.X, r.Y
}
// Rectangle 自动实现了 Shape、Movable 和 MovableShape 接口
type Circle struct {
Radius float64
X, Y float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
func (c *Circle) Move(dx, dy float64) {
c.X += dx
c.Y += dy
}
func (c Circle) GetPosition() (float64, float64) {
return c.X, c.Y
}
// Circle 也自动实现了相同的接口
2. 接口的使用
接口作为参数类型
// 使用接口作为参数,可以接受任何实现了该接口的类型
func printShapeInfo(s Shape) {
fmt.Printf("面积: %.2f\n", s.Area())
fmt.Printf("周长: %.2f\n", s.Perimeter())
}
func calculateTotalArea(shapes []Shape) float64 {
total := 0.0
for _, shape := range shapes {
total += shape.Area()
}
return total
}
func moveShape(m Movable, dx, dy float64) {
fmt.Printf("移动前位置: %.2f, %.2f\n", m.GetPosition())
m.Move(dx, dy)
fmt.Printf("移动后位置: %.2f, %.2f\n", m.GetPosition())
}
// 使用示例
func interfaceUsageExample() {
rect := Rectangle{Width: 5, Height: 3, X: 0, Y: 0}
circle := Circle{Radius: 2.5, X: 10, Y: 10}
fmt.Println("=== 矩形信息 ===")
printShapeInfo(rect)
fmt.Println("=== 圆形信息 ===")
printShapeInfo(circle)
shapes := []Shape{rect, circle}
totalArea := calculateTotalArea(shapes)
fmt.Printf("总面积: %.2f\n", totalArea)
fmt.Println("=== 移动矩形 ===")
moveShape(&rect, 5, 3)
fmt.Println("=== 移动圆形 ===")
moveShape(&circle, -2, 4)
}
接口作为返回值类型
type ShapeFactory struct{}
func (sf ShapeFactory) CreateRectangle(width, height float64) Shape {
return Rectangle{Width: width, Height: height}
}
func (sf ShapeFactory) CreateCircle(radius float64) Shape {
return Circle{Radius: radius}
}
func (sf ShapeFactory) CreateRandomShape() Shape {
rand.Seed(time.Now().UnixNano())
if rand.Intn(2) == 0 {
return Rectangle{Width: rand.Float64() * 10, Height: rand.Float64() * 10}
}
return Circle{Radius: rand.Float64() * 5}
}
// 使用示例
func factoryExample() {
factory := ShapeFactory{}
rect := factory.CreateRectangle(4, 6)
circle := factory.CreateCircle(3)
random := factory.CreateRandomShape()
shapes := []Shape{rect, circle, random}
for i, shape := range shapes {
fmt.Printf("图形 %d: 面积 = %.2f, 周长 = %.2f\n",
i+1, shape.Area(), shape.Perimeter())
}
}
3. 空接口与类型断言
空接口 interface{}
// 空接口可以存储任何类型的值
func printAnything(value interface{}) {
fmt.Printf("值: %v, 类型: %T\n", value, value)
}
func processValues(values ...interface{}) {
for i, value := range values {
fmt.Printf("参数 %d: %v (类型: %T)\n", i+1, value, value)
}
}
// 使用示例
func emptyInterfaceExample() {
var anything interface{}
anything = 42
printAnything(anything) // 值: 42, 类型: int
anything = "Hello"
printAnything(anything) // 值: Hello, 类型: string
anything = []int{1, 2, 3}
printAnything(anything) // 值: [1 2 3], 类型: []int
processValues(1, "hello", 3.14, true, []string{"a", "b"})
}
类型断言
// 类型断言语法:value.(Type)
func processInterface(value interface{}) {
// 安全的类型断言(带检查)
if str, ok := value.(string); ok {
fmt.Printf("字符串值: %s, 长度: %d\n", str, len(str))
} else if num, ok := value.(int); ok {
fmt.Printf("整数值: %d, 双倍: %d\n", num, num*2)
} else if slice, ok := value.([]int); ok {
fmt.Printf("整数切片: %v, 长度: %d\n", slice, len(slice))
} else {
fmt.Printf("未知类型: %T\n", value)
}
}
// 使用 switch 进行类型断言
func processInterfaceSwitch(value interface{}) {
switch v := value.(type) {
case string:
fmt.Printf("字符串: %s\n", v)
case int:
fmt.Printf("整数: %d\n", v)
case float64:
fmt.Printf("浮点数: %.2f\n", v)
case bool:
fmt.Printf("布尔值: %v\n", v)
case []int:
fmt.Printf("整数切片: %v\n", v)
case Rectangle:
fmt.Printf("矩形: %.2f x %.2f\n", v.Width, v.Height)
case Shape:
fmt.Printf("图形面积: %.2f\n", v.Area())
default:
fmt.Printf("未知类型: %T, 值: %v\n", v, v)
}
}
// 使用示例
func typeAssertionExample() {
values := []interface{}{
"Hello World",
42,
3.14,
true,
[]int{1, 2, 3, 4, 5},
Rectangle{Width: 5, Height: 3},
Circle{Radius: 2.5},
}
fmt.Println("=== 使用 if-else 类型断言 ===")
for _, value := range values {
processInterface(value)
}
fmt.Println("\n=== 使用 switch 类型断言 ===")
for _, value := range values {
processInterfaceSwitch(value)
}
}
接口高级特性
1. 接口组合
基础接口组合
package main
import "fmt" // 导入格式化输出包
// 定义基础接口 - 说话能力
type Speaker interface {
Speak() string // 说话方法,返回说话内容
}
// 定义基础接口 - 行走能力
type Walker interface {
Walk() string // 行走方法,返回行走描述
}
// 定义基础接口 - 进食能力
type Eater interface {
Eat(food string) string // 进食方法,接受食物参数,返回进食描述
}
// 组合接口 - 动物接口,组合了说话和行走能力
type Animal interface {
Speaker // 嵌入 Speaker 接口
Walker // 嵌入 Walker 接口
}
// 组合接口 - 人类接口,组合了动物和进食能力
type Human interface {
Animal // 嵌入 Animal 接口(包含 Speaker 和 Walker)
Eater // 嵌入 Eater 接口
}
// 定义狗的结构体
type Dog struct {
name string // 狗的名字
}
// 为 Dog 实现 Speaker 接口的 Speak 方法
func (d *Dog) Speak() string {
return fmt.Sprintf("%s says: Woof!", d.name) // 返回狗叫声
}
// 为 Dog 实现 Walker 接口的 Walk 方法
func (d *Dog) Walk() string {
return fmt.Sprintf("%s is walking on four legs", d.name) // 返回四条腿走路的描述
}
// 定义人的结构体
type Person struct {
name string // 人的名字
age int // 人的年龄
}
// 为 Person 实现 Speaker 接口的 Speak 方法
func (p *Person) Speak() string {
return fmt.Sprintf("%s says: Hello!", p.name) // 返回问候语
}
// 为 Person 实现 Walker 接口的 Walk 方法
func (p *Person) Walk() string {
return fmt.Sprintf("%s is walking on two legs", p.name) // 返回两条腿走路的描述
}
// 为 Person 实现 Eater 接口的 Eat 方法
func (p *Person) Eat(food string) string {
return fmt.Sprintf("%s is eating %s", p.name, food) // 返回进食描述
}
// 主函数
func main() {
// 创建 Dog 实例,Dog 实现了 Animal 接口
dog := &Dog{name: "Buddy"}
// 创建 Person 实例,Person 实现了 Human 接口(包含 Animal)
person := &Person{name: "Alice", age: 25}
// 声明 Animal 接口变量
var animal Animal
// 将 dog 赋值给 animal 接口变量
animal = dog
fmt.Println(animal.Speak()) // 调用狗的说话方法
fmt.Println(animal.Walk()) // 调用狗的行走方法
// 将 person 赋值给 animal 接口变量
animal = person
fmt.Println(animal.Speak()) // 调用人的说话方法
fmt.Println(animal.Walk()) // 调用人的行走方法
// 声明 Human 接口变量并赋值为 person
var human Human = person
fmt.Println(human.Eat("pizza")) // 调用人的进食方法
}
// 定义基础接口
type Reader interface {
Read([]byte) (int, error)
}
type Writer interface {
Write([]byte) (int, error)
}
type Closer interface {
Close() error
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
// 实现组合接口的类型
type File struct {
name string
data []byte
pos int
}
func (f *File) Read(p []byte) (int, error) {
if f.pos >= len(f.data) {
return 0, fmt.Errorf("EOF")
}
n := copy(p, f.data[f.pos:])
f.pos += n
return n, nil
}
func (f *File) Write(p []byte) (int, error) {
f.data = append(f.data, p...)
return len(p), nil
}
func (f *File) Close() error {
fmt.Printf("文件 %s 已关闭\n", f.name)
return nil
}
// File 自动实现了 Reader, Writer, ReadWriter, ReadWriteCloser 接口
复杂接口组合示例
// 数据处理相关接口
type Validator interface {
Validate() error
}
type Transformer interface {
Transform() error
}
type Persister interface {
Save() error
Load() error
}
type Notifier interface {
NotifySuccess()
NotifyError(error)
}
// 组合成复杂的数据处理接口
type DataProcessor interface {
Validator
Transformer
Persister
Notifier
}
// 用户数据处理器
type UserDataProcessor struct {
users []User
valid bool
}
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func (udp *UserDataProcessor) Validate() error {
for _, user := range udp.users {
if user.Name == "" {
return fmt.Errorf("用户名不能为空")
}
if !strings.Contains(user.Email, "@") {
return fmt.Errorf("无效的邮箱地址: %s", user.Email)
}
}
udp.valid = true
return nil
}
func (udp *UserDataProcessor) Transform() error {
if !udp.valid {
return fmt.Errorf("数据未验证,无法转换")
}
for i := range udp.users {
udp.users[i].Name = strings.TrimSpace(udp.users[i].Name)
udp.users[i].Email = strings.ToLower(udp.users[i].Email)
}
return nil
}
func (udp *UserDataProcessor) Save() error {
fmt.Printf("保存 %d 个用户数据\n", len(udp.users))
// 模拟保存到数据库
return nil
}
func (udp *UserDataProcessor) Load() error {
// 模拟从数据库加载
udp.users = []User{
{ID: 1, Name: "张三", Email: "zhangsan@example.com"},
{ID: 2, Name: "李四", Email: "lisi@example.com"},
}
fmt.Printf("加载了 %d 个用户数据\n", len(udp.users))
return nil
}
func (udp *UserDataProcessor) NotifySuccess() {
fmt.Println("✅ 数据处理成功完成")
}
func (udp *UserDataProcessor) NotifyError(err error) {
fmt.Printf("❌ 数据处理失败: %v\n", err)
}
// 使用组合接口
func processData(processor DataProcessor) {
if err := processor.Load(); err != nil {
processor.NotifyError(err)
return
}
if err := processor.Validate(); err != nil {
processor.NotifyError(err)
return
}
if err := processor.Transform(); err != nil {
processor.NotifyError(err)
return
}
if err := processor.Save(); err != nil {
processor.NotifyError(err)
return
}
processor.NotifySuccess()
}
// 使用示例
func interfaceCompositionExample() {
processor := &UserDataProcessor{}
processData(processor)
}
2. 接口的最佳实践
接口隔离原则
// 不好的设计 - 接口太大
type BadWorkerInterface interface {
Work()
Eat()
Sleep()
GetSalary() float64
SetSalary(float64)
GetName() string
SetName(string)
}
// 好的设计 - 接口分离
type Worker interface {
Work()
}
type Eater interface {
Eat()
}
type Sleeper interface {
Sleep()
}
type Employee interface {
GetSalary() float64
SetSalary(float64)
}
type Person interface {
GetName() string
SetName(string)
}
// 根据需要组合接口
type HumanWorker interface {
Worker
Eater
Sleeper
}
type StaffMember interface {
Person
Employee
}
接口命名约定
// 单方法接口通常以 -er 结尾
type Stringer interface {
String() string
}
type Reader interface {
Read([]byte) (int, error)
}
type Writer interface {
Write([]byte) (int, error)
}
type Closer interface {
Close() error
}
// 自定义接口示例
type Validator interface {
Validate() error
}
type Serializer interface {
Serialize() ([]byte, error)
}
type Deserializer interface {
Deserialize([]byte) error
}
type Processor interface {
Process() error
}
方法与接口实际应用
1. HTTP 服务器示例
定义处理器接口
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"time"
)
// HTTP 处理器接口
type Handler interface {
ServeHTTP(http.ResponseWriter, *http.Request)
}
// JSON 响应接口
type JSONResponder interface {
ToJSON() ([]byte, error)
}
// 用户模型
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
}
func (u User) ToJSON() ([]byte, error) {
return json.Marshal(u)
}
// 用户服务
type UserService struct {
users map[int]User
}
func NewUserService() *UserService {
return &UserService{
users: make(map[int]User),
}
}
func (us *UserService) GetUser(id int) (User, bool) {
user, exists := us.users[id]
return user, exists
}
func (us *UserService) CreateUser(name, email string) User {
id := len(us.users) + 1
user := User{
ID: id,
Name: name,
Email: email,
CreatedAt: time.Now(),
}
us.users[id] = user
return user
}
func (us *UserService) GetAllUsers() []User {
users := make([]User, 0, len(us.users))
for _, user := range us.users {
users = append(users, user)
}
return users
}
// 用户处理器
type UserHandler struct {
service *UserService
}
func NewUserHandler(service *UserService) *UserHandler {
return &UserHandler{service: service}
}
func (uh *UserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
uh.handleGet(w, r)
case "POST":
uh.handlePost(w, r)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func (uh *UserHandler) handleGet(w http.ResponseWriter, r *http.Request) {
idStr := r.URL.Query().Get("id")
if idStr != "" {
// 获取单个用户
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "Invalid user ID", http.StatusBadRequest)
return
}
user, exists := uh.service.GetUser(id)
if !exists {
http.Error(w, "User not found", http.StatusNotFound)
return
}
uh.writeJSONResponse(w, user)
} else {
// 获取所有用户
users := uh.service.GetAllUsers()
uh.writeJSONResponse(w, users)
}
}
func (uh *UserHandler) handlePost(w http.ResponseWriter, r *http.Request) {
var req struct {
Name string `json:"name"`
Email string `json:"email"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}
user := uh.service.CreateUser(req.Name, req.Email)
uh.writeJSONResponse(w, user)
}
func (uh *UserHandler) writeJSONResponse(w http.ResponseWriter, data interface{}) {
w.Header().Set("Content-Type", "application/json")
if responder, ok := data.(JSONResponder); ok {
jsonData, err := responder.ToJSON()
if err != nil {
http.Error(w, "Failed to serialize", http.StatusInternalServerError)
return
}
w.Write(jsonData)
} else {
json.NewEncoder(w).Encode(data)
}
}
2. 策略模式实现
支付处理系统
// 支付策略接口
type PaymentProcessor interface {
ProcessPayment(amount float64) error
GetPaymentMethod() string
}
// 支付结果接口
type PaymentResult interface {
IsSuccess() bool
GetMessage() string
GetTransactionID() string
}
// 支付结果实现
type paymentResult struct {
success bool
message string
transactionID string
}
func (pr paymentResult) IsSuccess() bool {
return pr.success
}
func (pr paymentResult) GetMessage() string {
return pr.message
}
func (pr paymentResult) GetTransactionID() string {
return pr.transactionID
}
// 信用卡支付
type CreditCardProcessor struct {
CardNumber string
CVV string
}
func (ccp *CreditCardProcessor) ProcessPayment(amount float64) error {
fmt.Printf("处理信用卡支付: ¥%.2f\n", amount)
fmt.Printf("卡号: %s, CVV: %s\n", ccp.maskCardNumber(), ccp.CVV)
// 模拟支付处理
time.Sleep(time.Millisecond * 100)
if amount > 10000 {
return fmt.Errorf("信用卡单次支付限额为 ¥10,000")
}
return nil
}
func (ccp *CreditCardProcessor) GetPaymentMethod() string {
return "信用卡"
}
func (ccp *CreditCardProcessor) maskCardNumber() string {
if len(ccp.CardNumber) < 4 {
return ccp.CardNumber
}
return "**** **** **** " + ccp.CardNumber[len(ccp.CardNumber)-4:]
}
// 支付宝支付
type AlipayProcessor struct {
Account string
}
func (ap *AlipayProcessor) ProcessPayment(amount float64) error {
fmt.Printf("处理支付宝支付: ¥%.2f\n", amount)
fmt.Printf("账户: %s\n", ap.Account)
// 模拟支付处理
time.Sleep(time.Millisecond * 50)
return nil
}
func (ap *AlipayProcessor) GetPaymentMethod() string {
return "支付宝"
}
// 微信支付
type WechatProcessor struct {
OpenID string
}
func (wp *WechatProcessor) ProcessPayment(amount float64) error {
fmt.Printf("处理微信支付: ¥%.2f\n", amount)
fmt.Printf("OpenID: %s\n", wp.OpenID)
// 模拟支付处理
time.Sleep(time.Millisecond * 80)
return nil
}
func (wp *WechatProcessor) GetPaymentMethod() string {
return "微信支付"
}
// 支付上下文
type PaymentContext struct {
processor PaymentProcessor
}
func NewPaymentContext(processor PaymentProcessor) *PaymentContext {
return &PaymentContext{processor: processor}
}
func (pc *PaymentContext) SetProcessor(processor PaymentProcessor) {
pc.processor = processor
}
func (pc *PaymentContext) ExecutePayment(amount float64) PaymentResult {
fmt.Printf("=== 开始支付流程 ===\n")
fmt.Printf("支付方式: %s\n", pc.processor.GetPaymentMethod())
err := pc.processor.ProcessPayment(amount)
if err != nil {
return paymentResult{
success: false,
message: err.Error(),
transactionID: "",
}
}
transactionID := pc.generateTransactionID()
return paymentResult{
success: true,
message: "支付成功",
transactionID: transactionID,
}
}
func (pc *PaymentContext) generateTransactionID() string {
return fmt.Sprintf("TXN_%d", time.Now().UnixNano())
}
// 使用示例
func paymentExample() {
// 创建不同的支付处理器
creditCard := &CreditCardProcessor{
CardNumber: "1234567812345678",
CVV: "123",
}
alipay := &AlipayProcessor{
Account: "user@example.com",
}
wechat := &WechatProcessor{
OpenID: "wx_openid_123456",
}
// 创建支付上下文
paymentCtx := NewPaymentContext(creditCard)
// 使用信用卡支付
result := paymentCtx.ExecutePayment(5000)
fmt.Printf("支付结果: %s (ID: %s)\n\n", result.GetMessage(), result.GetTransactionID())
// 切换到支付宝
paymentCtx.SetProcessor(alipay)
result = paymentCtx.ExecutePayment(3000)
fmt.Printf("支付结果: %s (ID: %s)\n\n", result.GetMessage(), result.GetTransactionID())
// 切换到微信支付
paymentCtx.SetProcessor(wechat)
result = paymentCtx.ExecutePayment(1500)
fmt.Printf("支付结果: %s (ID: %s)\n\n", result.GetMessage(), result.GetTransactionID())
// 尝试超额支付
paymentCtx.SetProcessor(creditCard)
result = paymentCtx.ExecutePayment(15000)
fmt.Printf("支付结果: %s\n", result.GetMessage())
}
3. 观察者模式实现
事件通知系统
// 观察者接口
type Observer interface {
Update(event Event)
GetID() string
}
// 事件接口
type Event interface {
GetType() string
GetData() interface{}
GetTimestamp() time.Time
}
// 主题接口
type Subject interface {
Attach(Observer)
Detach(string) // 通过 ID 移除观察者
Notify(Event)
}
// 事件实现
type event struct {
eventType string
data interface{}
timestamp time.Time
}
func NewEvent(eventType string, data interface{}) Event {
return &event{
eventType: eventType,
data: data,
timestamp: time.Now(),
}
}
func (e *event) GetType() string {
return e.eventType
}
func (e *event) GetData() interface{} {
return e.data
}
func (e *event) GetTimestamp() time.Time {
return e.timestamp
}
// 邮件通知观察者
type EmailNotifier struct {
id string
email string
}
func NewEmailNotifier(id, email string) *EmailNotifier {
return &EmailNotifier{id: id, email: email}
}
func (en *EmailNotifier) Update(event Event) {
fmt.Printf("[邮件通知 %s] %s 事件通知发送到 %s\n",
en.id, event.GetType(), en.email)
fmt.Printf(" 事件数据: %v\n", event.GetData())
fmt.Printf(" 事件时间: %s\n", event.GetTimestamp().Format("2006-01-02 15:04:05"))
}
func (en *EmailNotifier) GetID() string {
return en.id
}
// 短信通知观察者
type SMSNotifier struct {
id string
phone string
}
func NewSMSNotifier(id, phone string) *SMSNotifier {
return &SMSNotifier{id: id, phone: phone}
}
func (sn *SMSNotifier) Update(event Event) {
fmt.Printf("[短信通知 %s] %s 事件通知发送到 %s\n",
sn.id, event.GetType(), sn.phone)
fmt.Printf(" 事件数据: %v\n", event.GetData())
}
func (sn *SMSNotifier) GetID() string {
return sn.id
}
// 日志观察者
type Logger struct {
id string
}
func NewLogger(id string) *Logger {
return &Logger{id: id}
}
func (l *Logger) Update(event Event) {
fmt.Printf("[日志记录 %s] 记录事件: %s\n", l.id, event.GetType())
fmt.Printf(" 数据: %v\n", event.GetData())
fmt.Printf(" 时间: %s\n", event.GetTimestamp().Format("2006-01-02 15:04:05"))
}
func (l *Logger) GetID() string {
return l.id
}
// 事件管理器(主题实现)
type EventManager struct {
observers map[string]Observer
}
func NewEventManager() *EventManager {
return &EventManager{
observers: make(map[string]Observer),
}
}
func (em *EventManager) Attach(observer Observer) {
em.observers[observer.GetID()] = observer
fmt.Printf("观察者 %s 已订阅事件通知\n", observer.GetID())
}
func (em *EventManager) Detach(id string) {
if _, exists := em.observers[id]; exists {
delete(em.observers, id)
fmt.Printf("观察者 %s 已取消订阅\n", id)
}
}
func (em *EventManager) Notify(event Event) {
fmt.Printf("\n=== 广播事件: %s ===\n", event.GetType())
for _, observer := range em.observers {
observer.Update(event)
fmt.Println()
}
}
func (em *EventManager) GetObserverCount() int {
return len(em.observers)
}
// 使用示例
func observerPatternExample() {
// 创建事件管理器
eventManager := NewEventManager()
// 创建观察者
emailNotifier := NewEmailNotifier("email1", "admin@example.com")
smsNotifier := NewSMSNotifier("sms1", "13800138000")
logger := NewLogger("logger1")
// 注册观察者
eventManager.Attach(emailNotifier)
eventManager.Attach(smsNotifier)
eventManager.Attach(logger)
// 触发事件
userLoginEvent := NewEvent("UserLogin", map[string]interface{}{
"user_id": 12345,
"username": "john_doe",
"login_ip": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
})
eventManager.Notify(userLoginEvent)
// 触发另一个事件
orderCreatedEvent := NewEvent("OrderCreated", map[string]interface{}{
"order_id": "ORDER123456",
"customer_id": 789,
"amount": 299.99,
"products": []string{"Product A", "Product B"},
})
eventManager.Notify(orderCreatedEvent)
// 移除一个观察者
eventManager.Detach("sms1")
// 再次触发事件
systemErrorEvent := NewEvent("SystemError", map[string]interface{}{
"error_code": 500,
"error_message": "Database connection failed",
"service": "user-service",
})
eventManager.Notify(systemErrorEvent)
fmt.Printf("当前观察者数量: %d\n", eventManager.GetObserverCount())
}
总结
最佳实践总结
方法设计原则
选择合适的接收者类型(值 vs 指针)
保持方法职责单一
合理命名方法
接口设计原则
接口应该小而专注
遵循接口隔离原则
使用组合而非继承
实际应用指导
利用接口实现多态
使用接口进行依赖注入
通过接口实现设计模式
Go 语言的方法和接口为面向对象编程提供了强大而灵活的工具。通过合理使用这些特性,可以编写出更加模块化、可扩展和可维护的代码。接口的隐式实现机制使得代码耦合度更低,而方法的接收者机制提供了清晰的对象行为定义方式。
作者:admin 创建时间:2025-08-19 00:09
最后编辑:admin 更新时间:2025-11-02 22:25
最后编辑:admin 更新时间:2025-11-02 22:25