flyfei

接口(interface)

1. 语法讲解

接口定义

接口是Go语言中实现多态的重要特性,它定义了一组方法签名,而不包含具体实现。

type 接口名 interface {
    方法1(参数列表) 返回值列表
    方法2(参数列表) 返回值列表
    // ...
}  

当一个类型实现了接口中所有方法,就视为实现了该接口,无需显式声明。

空接口

空接口interface{}不包含任何方法,可以存储任意类型的值,类似于Java中的Object或TypeScript中的any。

var anything interface{}
anything = 42      // 整数
anything = "hello" // 字符串

2. 应用场景

真实业务场景:电商支付系统 在实际电商系统中,需要接入多种支付方式(支付宝、微信、银联等),每种支付方式都有相同的核心操作(支付、查询、退款),但具体实现不同。使用接口可以统一管理这些支付方式,提高代码可扩展性和可维护性。

3. 编程实例

package main

import "fmt"

// 支付接口定义
type Payment interface {
    Pay(amount float64) (string, error)
    Refund(transactionID string, amount float64) (string, error)
    Query(transactionID string) (string, error)
}

// 支付宝支付实现
type Alipay struct {
    AppID     string
    AppSecret string
    MerchantID string
}

func (a Alipay) Pay(amount float64) (string, error) {
    // 调用支付宝SDK实现支付逻辑
    return fmt.Sprintf("ALIPAY-%d", time.Now().Unix()), nil
}

func (a Alipay) Refund(transactionID string, amount float64) (string, error) {
    // 调用支付宝退款接口
    return fmt.Sprintf("ALIPAY-REFUND-%s", transactionID), nil
}

func (a Alipay) Query(transactionID string) (string, error) {
    // 查询支付宝交易状态
    return "SUCCESS", nil
}

// 微信支付实现
type WechatPay struct {
    AppID     string
    MchID     string
    APIKey    string
}

func (w WechatPay) Pay(amount float64) (string, error) {
    // 调用微信支付API
    return fmt.Sprintf("WECHAT-%d", time.Now().Unix()), nil
}

func (w WechatPay) Refund(transactionID string, amount float64) (string, error) {
    // 调用微信退款API
    return fmt.Sprintf("WECHAT-REFUND-%s", transactionID), nil
}

func (w WechatPay) Query(transactionID string) (string, error) {
    // 查询微信支付状态
    return "SUCCESS", nil
}

// 支付处理函数 - 多态体现
func ProcessPayment(p Payment, amount float64) (string, error) {
    // 统一的支付处理逻辑
    fmt.Println("开始处理支付请求...")
    transactionID, err := p.Pay(amount)
    if err != nil {
        return "", err
    }
    fmt.Printf("支付成功,交易号: %s\n", transactionID)
    return transactionID, nil
}

func main() {
    // 初始化支付方式
    alipay := Alipay{
        AppID: "2021000123456789",
        AppSecret: "your_app_secret",
        MerchantID: "2088xxxxxx",
    }
    
    wechatPay := WechatPay{
        AppID: "wx1234567890abcdef",
        MchID: "1230000109",
        APIKey: "your_api_key",
    }
    
    // 使用不同的支付方式处理支付
    transactions := []struct{
        payment Payment
        amount float64
        name string
    }{
        {alipay, 199.99, "支付宝"},
        {wechatPay, 299.99, "微信支付"},
    }
    
    for _, t := range transactions {
        fmt.Printf("\n使用%s支付:\n", t.name)
        transactionID, err := ProcessPayment(t.payment, t.amount)
        if err != nil {
            fmt.Printf("支付失败: %v\n", err)
            continue
        }
        fmt.Printf("交易完成: %s\n", transactionID)
    }
}

4. 其他用法

类型断言和类型判断

package main

import "fmt"

// 类型断言基本用法
func processEmptyInterface(value interface{}) {
    // 类型断言
    if str, ok := value.(string); ok {
        fmt.Printf("字符串值: %s\n", str)
    } else if num, ok := value.(int); ok {
        fmt.Printf("整数值: %d\n", num)
    } else {
        fmt.Printf("其他类型: %T\n", value)
    }
    
    // 类型switch
    switch v := value.(type) {
    case string:
        fmt.Printf("这是字符串: %s\n", v)
    case int:
        fmt.Printf("这是整数: %d\n", v)
    case float64:
        fmt.Printf("这是浮点数: %f\n", v)
    case bool:
        fmt.Printf("这是布尔值: %t\n", v)
    default:
        fmt.Printf("未知类型: %T\n", v)
    }
}

// 业务场景:处理多种类型的API响应
type APIResponse struct {
    Data interface{}
    Code int
    Message string
}

func handleAPIResponse(response APIResponse) {
    // 根据不同类型的数据进行不同处理
    switch data := response.Data.(type) {
    case map[string]interface{}:
        fmt.Println("处理对象数据:")
        for key, value := range data {
            fmt.Printf("  %s: %v\n", key, value)
        }
    case []interface{}:
        fmt.Printf("处理数组数据,长度: %d\n", len(data))
        for i, item := range data {
            fmt.Printf("  [%d]: %v\n", i, item)
        }
    case string:
        fmt.Printf("处理字符串数据: %s\n", data)
    case float64:
        fmt.Printf("处理数值数据: %.2f\n", data)
    default:
        fmt.Printf("未知数据类型: %T\n", data)
    }
}

func main() {
    // 测试类型处理
    processEmptyInterface("Hello")
    processEmptyInterface(42)
    processEmptyInterface(3.14)
    processEmptyInterface(true)
    
    // 模拟API响应处理
    responses := []APIResponse{
        {Data: map[string]interface{}{"name": "张三", "age": 25}, Code: 200},
        {Data: []interface{}{"商品1", "商品2", "商品3"}, Code: 200},
        {Data: "成功消息", Code: 200},
    }
    
    for _, resp := range responses {
        handleAPIResponse(resp)
        fmt.Println()
    }
}

接口组合

package main

import "fmt"

// 基础接口定义
type Reader interface {
    Read() []byte
}

type Writer interface {
    Write(data []byte) error
}

type Closer interface {
    Close() error
}

// 接口组合
type ReadWriteCloser interface {
    Reader
    Writer
    Closer
}

// 文件操作实现
type FileOperation struct {
    filename string
    isOpen bool
}

func (f *FileOperation) Read() []byte {
    fmt.Printf("读取文件 %s\n", f.filename)
    return []byte("文件内容")
}

func (f *FileOperation) Write(data []byte) error {
    fmt.Printf("向文件 %s 写入数据: %s\n", f.filename, string(data))
    return nil
}

func (f *FileOperation) Close() error {
    f.isOpen = false
    fmt.Printf("关闭文件 %s\n", f.filename)
    return nil
}

// 使用组合接口
func processFile(rwc ReadWriteCloser, data []byte) {
    rwc.Read()
    rwc.Write(data)
    rwc.Close()
}

func main() {
    fileOp := &FileOperation{filename: "test.txt", isOpen: true}
    data := []byte("新的内容")
    
    processFile(fileOp, data)
}

5. 课时总结