MST

星途 面试题库

面试题:Go语言接口版本控制中的兼容性问题

考虑一个Go项目,其中有一个接口`Payment`,多个支付实现类实现了这个接口。现在要对`Payment`接口进行版本控制升级,新接口`PaymentV2`增加了一个`Refund`方法。在不破坏原有代码兼容性,且能逐步迁移到新接口的情况下,你会如何设计代码结构?请详细阐述设计思路,并提供关键代码片段。
28.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 定义新旧接口:分别定义 Payment 接口和 PaymentV2 接口,PaymentV2 继承 Payment 接口以保持一定的兼容性。
  2. 实现类处理:让新的支付实现类实现 PaymentV2 接口,旧的实现类依然实现 Payment 接口。
  3. 适配层:创建一个适配层,将实现了 Payment 接口的旧类适配成 PaymentV2 接口,在适配层中对于新增的 Refund 方法可以提供默认实现或者抛出不支持的异常。
  4. 逐步迁移:在业务逻辑中,可以逐步将使用旧接口的地方替换为新接口,在替换过程中通过适配层保证旧实现类依然可用。

关键代码片段

// 定义旧接口
type Payment interface {
    Pay(amount float64) error
}

// 定义新接口,继承旧接口
type PaymentV2 interface {
    Payment
    Refund(amount float64) error
}

// 旧的支付实现类
type OldPayment struct{}

func (op *OldPayment) Pay(amount float64) error {
    // 支付逻辑
    return nil
}

// 适配层,将 OldPayment 适配为 PaymentV2
type OldPaymentAdapter struct {
    OldPayment *OldPayment
}

func (opa *OldPaymentAdapter) Pay(amount float64) error {
    return opa.OldPayment.Pay(amount)
}

func (opa *OldPaymentAdapter) Refund(amount float64) error {
    // 可以提供默认实现,比如不支持退款
    return errors.New("refund is not supported")
}

// 新的支付实现类
type NewPayment struct{}

func (np *NewPayment) Pay(amount float64) error {
    // 支付逻辑
    return nil
}

func (np *NewPayment) Refund(amount float64) error {
    // 退款逻辑
    return nil
}

在业务代码中,可以这样使用:

func main() {
    var paymentV2 PaymentV2
    oldPayment := &OldPayment{}
    paymentV2 = &OldPaymentAdapter{OldPayment: oldPayment}
    // 调用 Pay 方法
    err := paymentV2.Pay(100)
    if err != nil {
        fmt.Println(err)
    }
    // 调用 Refund 方法
    err = paymentV2.Refund(100)
    if err != nil {
        fmt.Println(err)
    }

    newPayment := &NewPayment{}
    paymentV2 = newPayment
    // 调用 Pay 方法
    err = paymentV2.Pay(100)
    if err != nil {
        fmt.Println(err)
    }
    // 调用 Refund 方法
    err = paymentV2.Refund(100)
    if err != nil {
        fmt.Println(err)
    }
}