12.5 并发实践与模式(Pattern) 12.5.1 确保 API 不涉及并发 并发是一种实现细节,良好的 API 设计应该尽可能隐藏实现细节。这样可以在不改变代码调用方式的情况下,改变代码的内部工作方式。 实际上,这意味着永远不应该在 API 的类型、函数和方法中暴露通道或互斥锁(将在“12.
12.1 何时使用并发 首先要确保程序确实能从并发中获益。 人们之所以被并发所吸引,是因为他们相信并发程序运行得更快。然而,情况并非总是如此。更多的并发并不会自动让程序变快,反而可能让代码更难理解。关键在于理解:并发 ≠ 并行。并发是一种用来更好地组织你试图解决的问题的工具。 并发代码是否并行(同时
理解异步编程时,一个常见误区是将其简单等同于“提升程序运行速度”或“让多个任务同时执行”。实际上,异步机制首先解决的并不是计算性能问题,而是执行资源的利用效率问题:当程序发起一个无法立即完成的操作,尤其是网络、磁盘、数据库等 I/O 操作时,是否有必要让当前执行线程始终阻塞并等待该操作完成。 以远程
9.1 错误处理基础 如“5.1.3 多返回值<86页>”所述,Go 语言通过将 error 类型的值作为函数最后一个返回值来处理错误。这完全是一种约定俗成的做法,但该约定极其严格,永远不应被打破。当函数按预期执行时,error 参数返回 nil。若出现异常,则返回错误值。调用函数随后通过将 err
7.10 接口与 nil 在讨论指针时(“六 指针<105页>”),曾提到了 nil——指针类型的零值(Zero Value)。虽然 nil 也可以用来表示接口实例的零值,但其行为比具体类型(Concrete Type)更为复杂。 要理解接口与 nil 的关系,需要先了解 Go 接口的底层实现机制。
Python vs C++ C++ 是静态类型语言,所谓静态类型,就是变量、表达式和函数参数的类型在编译阶段就已经确定。 对于基于虚函数的动态多态,编译器在编译阶段已经知道调用表达式的静态类型、类的继承关系以及虚函数的接口,因此可以预先确定虚函数表的布局,并生成“从对象的虚表中取某个固定槽位并调用”
Accept interfaces 对于那些你只依赖其行为的复杂对象,应当接受接口类型作为参数,这样就不会与该功能的某个具体实现产生耦合。这样做可以为使用者提供更大的灵活性,同时也能提高代码的可测试性。 不推荐: func New(f *os.File) (*Parser, error) {
/
7.6 接口快速入门 虽然 Go 的并发模型(详见“十二 Go 并发编程<251页>”)获得了所有的关注,但 Go 设计的真正明星是其隐式接口,这是 Go 中唯一的抽象类型。让我们看看是什么让它如此出色。 首先,看一下如何声明接口。接口很简单,本质上接口与其他用户定义类型一样,都使用 type 关键
7.3 用于枚举的 iota 许多编程语言中都提供了枚举类型(Enum),用以表示一组固定的值。Go 语言中没有内置的枚举类型,但提供了 iota,它允许为一组常量赋予递增的整数值。 iota 的最佳用法是首先定义一个基于 int 的新类型,该类型将表示所有有效值。例如: type MailCate
7.4 类型嵌入 这条“优先使用对象组合而非类继承”的软件工程准则,最早可追溯到 1994 年 Erich Gamma 等四人(俗称“四人帮”)所著的《设计模式》经典著作。虽然 Go 语言没有传统面向对象的继承机制,但通过以下原生特性实现了更优雅的代码复用: type Employee struct