美文网首页
Golang整洁接口最佳实践

Golang整洁接口最佳实践

作者: 翟志军 | 来源:发表于2021-06-20 11:18 被阅读0次

    翻译自:https://qvault.io/2020/03/15/best-practices-for-writing-clean-interfaces-in-go/

    woman-3169726_640.jpg

    Go中的接口允许我们将不同的类型暂时视为同一数据类型。它们是 Go 程序员工具箱的核心,但新的 Go 开发者往往会使用不当......导致代码难以阅读,易于产生Bug。让我们来看看Golang接口的一些最佳实践。

    我经常以标准库为例,来说明如何写出干净的Go接口。标准的错误接口很简单:

    type error interface {
        Error() string
    }
    

    error接口封装了任何有Error()方法的类型。该方法不接受任何参数,并返回一个字符串。例如,让我们定义一个表示网络问题的结构。

    type networkProblem struct {
        message string
        code    int
    }
    

    然后,我们定义一个Error()方法:

    func (np networkProblem) Error() string {
        return fmt.Sprintf("network error! message: %s, code: %v", np.message, np.code)
    }
    

    Now, we can use an instance of the networkProblem struct wherever an error is accepted.

    现在,我们可以在任何接受到错误的地方使用networkProblem结构的实例:

    func handleErr(err error) {
        fmt.Println(err.Error())
    }
    
    np := networkProblem{
        message: "we received a problem",
        code:    404,
    }
    
    handleErr(np)
    
    // prints "network error! message: we received a problem, code: 404"
    

    坚持小接口

    如果你只能从这篇文章中得到一条建议,那就是:让接口小一点! 接口的目的是为了定义准确表示一个想法或概念所必需的最小行为。

    下面是标准HTTP包中一个更大的接口的例子,它是定义最小行为的好例子:

    type File interface {
        io.Closer
        io.Reader
        io.Seeker
        Readdir(count int) ([]os.FileInfo, error)
        Stat() (os.FileInfo, error)
    }
    

    任何满足接口行为的类型都可以被HTTP包当作一个文件来处理。这很方便,因为HTTP包不需要知道它处理的是磁盘上的文件、网络缓冲区,还是简单的[]字节。

    接口应该没有满足类型的知识

    一个接口不应该关心具体的类型。

    下面,假设我们构建一个用于描述一辆汽车的组件的接口:

    type car interface {
        GetColor() string
        GetSpeed() int
        IsFiretruck() bool
    }
    

    GetColor()GetSpeed() 方法是汽车领域的知识。而 IsFiretruck() 则是反模式。此接口应该关注所有汽车的通用方法,而不应该关心它是否是一台消防车。 否则,我们还必须在这个接口中增加:IsPickup(), IsSedan(), IsTank() 等等,没完没了了。

    相反,当给定一个car的接口实例时,开发应该根据类型断言的原生功能来推断出子类型。或者,如果子接口需要一个子接口,它可以定义为:

    type firetruck interface {
        car
        HoseLength() int
    }
    

    firetruck接口继承了汽车的必要方法,并增加了一个额外的必要方法,使汽车成为消防车。

    接口不是类

    接口不是类,应该是小的。

    接口不需要构造函数或析构函数,因为它没有必要进行数据的初始化和销毁。

    接口在本质上不是分层的,尽管有语法糖来创建接口,而这些接口恰好是其他接口的超集。

    接口只负责定义函数签名,不关心其具体实现。在结构方法中,定义一个接口可以减少重复代码。例如,如果5种类型实现了错误接口,它们就需要分别实现Error()函数。

    相关文章

      网友评论

          本文标题:Golang整洁接口最佳实践

          本文链接:https://www.haomeiwen.com/subject/gyzhyltx.html