Go 中的 7 个常见接口错误

news/2025/2/13 0:23:32/

Go 仍然是一门新语言,如果你正在使用它,它很可能不是你的第一门编程语言。

不同的语言,既为你带来了经验,也带来了偏见。你用以前的任何语言做的事情,在 Go 中用相同的方法可能不是一个好主意。

学习 Go 不仅仅是学习一种新的语法。这也是学习一种新的思维方式来思考你的程序:

Go is a language for writing Go programs, not Java programs or Haskell programs or any other language’s programs. You need to think a different way to write good Go programs. But that takes time and effort, more than most will invest. So the usual story is to translate one program from another language into Go and see how it turns out. But translation misses idiom. A first attempt to write, for example, some Java construct in Go will likely fail, while a different Go-specific approach might succeed and illuminate. After 10 years of Java programming and 10 minutes of Go programming, any comparison of the language’s capabilities is unlikely to generate insight, yet here come the results, because that’s a modern programmer’s job.

Rob Pike Esmerelda’s Imagination

正如 Rob Pike 所建议的那样,如果你想提高围棋技能,需要投入时间和精力来学习这门语言的习语。

Go 在几件事上与其他传统语言不同,在本文中,我将重点介绍其中之一:接口。

下面列出了人们在编写 Go 接口时常犯的错误。这些在其他语言中可能不是错误,但在 Go 中,你需要忘记它们。或者至少,给一个机会,暂时不和他们一起工作,看看这会把你引向何方。

但在这之前

以下是阅读本文时要记住的事项列表。如果你已经熟悉它们,请随意跳过。

  • 接口隔离原则:不应强制客户端实现它不使用的接口,也不应强制客户端依赖于它们不使用的方法。

  • 多态性:一段代码根据它收到的具体数据改变其行为。

  • Liskov 替换原则:如果你的代码依赖于抽象,那么一个实现可以被另一个实现替换,而无需更改你的代码。

    抽象的目的不是模糊不清,而是创造一个新的语义层次,在这个层次上可以绝对精确。— E.W.迪克斯特拉

接口是精确包含用于编写程序的想法的概念。

以正确的方式使用接口可以带来简单性、可读性和 organic code 设计。

organic code 是代码会根据你在某个时间点所需的行为而增长。它不会强迫你提前考虑你的类型以及它们之间的关系,因为你很可能无法正确理解它们。

这就是为什么说 Go 偏爱组合而不是继承。你有一小组行为,你可以从中编写任何你想要的,而不是预定义由其他类型继承的类型并希望它们适合问题域。

Rob Pike 在 golang-nuts 论坛上解释了这种方法:

img

Go 的接口不是 Java 或 C# 接口的变体,它们远不止于此。它们是大规模编程和适应性强的演进设计的关键。

无论如何,理论已经足够了,让我们来看看最常见的错误:

1. 你创建了太多的接口

接口过多的术语称为接口污染 interface pollution.。当你在编写具体类型之前开始抽象时,就会发生这种情况。由于你无法预见你需要什么抽象,所以很容易写出太多的接口,这些接口在以后要么是错误的,要么是无用的。

Rob Pike 有一个很好的指南,可以帮助我们避免界面污染:

Don’t design with interfaces, discover them.

Rob Pike

Rob 在这里指出的是,你不需要提前考虑你需要什么抽象。你可以使用具体结构开始设计,并仅在设计需要时创建接口。通过这样做,你的代码会顺其自然的增长到预期的设计。

我仍然看到人们提前创建接口,因为他们认为他们将来可能需要多个实现。

我对他们说:

img

以一种好的方式懒惰。创建接口的最佳时机是你真正需要它的时候,而不是你预测需要它的时候。下面是一个通过提前思考创建接口的示例,以及它导致了什么。

无用的接口往往只有一个实现。它们只是增加了一个额外的间接级别,迫使程序员在真正想要实现时总是通过它们。

接口是有代价的:这是您在推理代码时需要记住的一个新概念。正如 Djikstra 所说,理想的界面必须是“a new semantic level in which one can be absolutely precise.”。

如果你的代码需要 Box 的概念,仅由 Box 实现的名为 Container 的额外接口没有带来任何好处,除了混淆。

因此,在创建接口之前,先问问自己:接口有多个实现吗?我强调使用了‘有’,因为‘将会有’假设了你能预测未来,而你不能。

2. 你有太多的方法

在 PHP 项目中,看到 10 种方法接口是很常见的。在 Go 中,接口很小,标准库中所有接口上的平均方法数为 2。

The bigger the interface the weaker the abstraction,这是 Go 谚语之一。正如 Rob Pike 所说,这是接口最重要的一点,这意味着接口越小,它就越有用。

接口可以拥有的实现越多,它的通用性就越强。如果你有一个包含大量方法的接口,则很难有它的多个实现。您拥有的方法越多,接口就越具体。它越具体,不同类型显示相同行为的可能性就越低。

有用接口的一个很好的例子是


http://www.ppmy.cn/news/1571562.html

相关文章

redis底层数据结构——链表

文章目录 定义内部实现总结 定义 链表提供了高效的节点重排能力,以及顺序性的节点访间方式,并且可以通过增删节点来灵活地调整链表的长度。 作为一种常用数据结构,链表内置在很多高级的编程语言里面,因为Redis使用的C语言并没有…

Android 系统面试问题

一.android gki和非gki的区别 Android GKI(Generic Kernel Image)和非GKI内核的主要区别在于内核设计和模块化程度,具体如下: 1. 内核设计 GKI:采用通用内核设计,与设备硬件分离,核心功能统一…

c++ haru生成pdf输出饼图

#define PI 3.14159265358979323846 // 绘制饼图的函数 void draw_pie_chart(HPDF_Doc pdf, HPDF_Page page, float *data, int data_count, float x, float y, float radius) { float total 0; int i; // 计算数据总和 for (i 0; i < data_count; i) { tot…

微信小程序地图开发总结-规划路线

在现代移动应用中&#xff0c;地图导航功能已成为必不可少的一部分。通过地图 API&#xff0c;我们可以轻松地在应用中集成位置服务和路径规划功能。本篇文章将带大家一起实现一个简单的路径导航功能&#xff0c;使用腾讯地图 API结合微信小程序&#xff0c;实现从当前位置到目…

《pytorch》——优化器的解析和使用

优化器简介 在 PyTorch 中&#xff0c;优化器&#xff08;Optimizer&#xff09;是用于更新模型参数以最小化损失函数的关键组件。在机器学习和深度学习领域&#xff0c;优化器是一个至关重要的工具&#xff0c;主要用于在模型训练过程中更新模型的参数&#xff0c;其目标是最…

【C#零基础从入门到精通】(二)——C#注释和命名法详解

【C#零基础从入门到精通】(二)——C#注释和命名法详解 C# 中的注释 定义 在 C# 里,注释是一种特殊的代码文本,它不会被编译器执行,主要用于对代码进行解释、说明,帮助开发者更好地理解代码的功能、用途、实现思路以及注意事项等,提升代码的可读性和可维护性。 注释类型…

【学习笔记】计算机网络(三)

第3章 数据链路层 文章目录 第3章 数据链路层3.1数据链路层的几个共同问题3.1.1 数据链路和帧3.1.2 三个基本功能3.1.3 其他功能 - 滑动窗口机制 3.2 点对点协议PPP(Point-to-Point Protocol)3.2.1 PPP 协议的特点3.2.2 PPP协议的帧格式3.2.3 PPP 协议的工作状态 3.3 使用广播信…

微信小程序(第一集)

app.json {// 定义小程序的所有页面路径&#xff0c;数组中的第一个页面是首页"pages": ["pages/index/index", // 首页"pages/logs/logs" // 日志页面],// 设置小程序的全局窗口外观&#xff08;比如导航栏和背景颜色&#xff09;"wind…