Go中的接口允许我们暂时将不同类型视为相同的数据类型。它们是围棋程序员工具带的核心,经常被新的围棋开发人员…不当使用。导致难以阅读和错误代码。让我们来看看Golang接口的一些最佳实践。
我经常把标准库作为编写干净Go的一个例子。标准错误接口很简单:
Error接口封装任何定义了Error()方法的类型。该方法不接受任何参数,并返回一个字符串。例如,让我们定义一个表示网络问题的结构:
Func(NP NetworkProblem)error()string{return fmt.Sprintf(";network error!消息:%s,代码:%v";,np.message,np.code)}。
现在,我们可以在任何接受错误的地方使用networkProblem结构的实例。
Func handleErr(Err Error){fmt.Println(err.Error())}np:=networkProblem{Message:";我们收到问题";,代码:404,}handleErr(NP)//打印";网络错误!消息:我们收到一个问题,代码:404";
如果您从本文中只学到了一条建议,那就是:保持接口小!接口旨在定义准确表示思想或概念所需的最小行为。
以下是一个较大接口的标准HTTP包中的一个示例,它是定义最小行为的一个很好的示例:
任何满足接口行为的类型都可以被HTTP包视为文件。这很方便,因为HTTP包不需要知道它正在处理的是磁盘上的文件、网络缓冲区还是简单的[]字节。
接口应该定义其他类型需要什么才能分类为该接口的成员。他们不应该知道在设计时恰好满足接口的任何类型。
例如,假设我们正在构建一个接口来描述定义汽车所需的组件。
GetColor()和GetSpeed()非常有意义,它们都是被限制在汽车范围内的方法。IsFireTruck()是一种反模式。我们正强制所有车辆申报是否为消防车。为了让这个模式有任何意义,我们需要一个可能的子类型的完整列表。IsPickUp()、IsSedan()、IsTank()…。它在哪里结束??
相反,当给定Car接口的实例时,开发人员应该依赖类型断言的本机功能来派生底层类型。或者,如果需要子接口,可以将其定义为:
它继承了Car所需的方法,并添加了一个额外的所需方法以使Car成为消防车。
接口没有需要创建或销毁数据的构造函数或解构函数。
接口本质上不是分层的,尽管创建恰好是其他接口超集的接口有语法上的好处。
接口定义函数签名,但不定义底层行为。创建接口通常不会使您的代码在结构方法方面枯竭。例如,如果五种类型满足Error接口,则它们都需要各自版本的error()函数。