## 介绍(Introduction) 最近,在 Slack 上我看过大量关于接口的问题。大多数时候,答案都很有技术性,并都关注了实现的细节。实现(细节)对于调试很有帮助,但实现对设计却毫无帮助。当用接口来设计代码时,行为才是主要需要关注的。 在这篇博文中,我希望提供一个不同的思考方式,关于接口,和用他们进行代码设计。我想让你停止关注于实现细节,而是关注于接口和具体的数据的关系。 ## 面向数据设计(Data Oriented Design) 我相信写 Go 代码,应该用...
-
接口不是值类型(Interface Values Are Valueless)
-
接口和反射的关系
接口是 Go 中用于抽象的基本工具之一。接口在值进行分配的时候存储类型信息。反射则是在运行时检查类型和值的方法。 Go 通过 `reflect` 包实现了反射。该包提供了一些类型和方法用于检查接口结构部分,不仅如此,它还可以在运行时进行值的修改。 在这篇文章中,我希望能说明接口结构的各部分和反射 API 之间的关系,并最终使得反射包变得更加容易理解。 ## 向一个接口分配一个值 一个接口编码了三件事:值,方法集,以及所存储的值的类型。 下图展示了一个接口的内部结构。...
-
深度剖析 Go 中的 Go 协程 (goroutines) -- Go 的并发
> Go 协程 (goroutine) 是指在后台中运行的轻量级执行线程,go 协程是 Go 中实现并发的关键组成部分。 在上次的课程中,我们学习了 Go 的并发模型。由于 Go 协程相对于传统操作系统中的线程 (thread) 是非常轻量级的,因此对于一个典型的 Go 应用来说,有数以千计的 Go 协程并发运行的情形是十分常见的。并发可以显著地提升应用的运行速度,并且可以帮助我们编写关注点分离(Separation of concerns,Soc)的代码。 ## 什么是 Go 协程...
-
Golang 中迭代读取 channel
欢迎再次来到我的 Go 语言私人教学课堂,今天我们的主题是,我曾经很难理解的 ( 还好现在已经理解了 ):在 Go 程中迭代读取 `channels`。 在开始之前,让我们先回忆一下。我们都知道,一个 Go 程的存活周期是建立在 main 进程之上的,举个例子: ```go package main import "fmt" func main() { go func() { fmt.Println("hello there") }() } ``` ...
-
Go test 少为人知的特性
大多数的 Go 程序员都知道和喜欢用 `go test`,这个测试工具来自于 Go 官方的 `gc` 工具链。(想要执行测试代码)这个命令可能是最简单的了,而且还能做得很漂亮。 大家都知道,运行 `go test` 命令将执行当前目录下的包的测试代码,它会寻找 `*_test.go` 文件,并在这些文件中,寻找符合 `TestXxx(*testing.T){}` 命名的函数和参数(即,接收 `*testing.T` 参数的函数,命名为 `TestXxx`,`Xxx` 可以是任何不以小写字符...
-
Go 功能:将 Go 程序员带向极限(Functional Go: Taking The Gopher to it's extremes)
## 功能范式(The Functional Paradigm) 函数式编程基于简单的规则,目的是使程序保持一致,使并行(更)人性化和简单化,函数是存粹的,它不会改变(变量的)状态,不会改变对象,也不共享状态,代码是声明式的,计算只不过是数学函数的一种实现。 我们来看一个纯粹的函数语言的函数例子: ``` isPalindrome :: (Eq a) => [a] -> Bool isPalindrome x = x == reverse x ``` 上面的代码是 ...