---
title: Java Stream 与 Go 的泛型缺口
date: '2018-09-27 22:12:13'
draft: false
summary: 集合处理抽象一旦形成习惯，就会更明显地暴露出 Go 在泛型到来之前的表达限制。
slug: java-11-stream-takewhile-and-go-generic-gap
syndication:
- platform: Weibo
  url: https://weibo.com/1648815335/GBkWDgVIb
tags:
- java
- stream
- golang
- generics
topics:
- software-engineering
type: post
---

`Java 11` 出来时，我想到的不是版本号本身，而是之前代码里留过的一个 `TODO` 终于可以收掉了：等新版本支持 `Stream` 的 `takeWhile` 优化。

这个 feature 虽然在 `Java 9` 就有，但 `9` 和 `10` 都是短命版本，很多团队不会专门为了这类增强去折腾升级。到了 `11` 这种长期支持版本，才更像是可以认真用起来的时间点。

我一直觉得，`Java 8` 引入 `Stream` 是一件影响被低估了的事。

因为它并不只是多了几个函数式 API，而是把大量原本只能靠 `for` 循环、`if` 嵌套手写的集合处理逻辑，拉到了一个更统一、更可组合的抽象层上。

这类抽象一旦用顺手，人的心智会发生变化。你会越来越习惯用 pipeline 去思考数据处理过程，而不是每次都回到命令式循环细节里。

也正因为这样，很多人从 `Java` 切到 `Go` 时，会明显感觉少了点什么。

问题往往不在“Go 没有库”，而在于在泛型出现之前，`Go` 很难自然长出一套真正通用、类型安全、又足够好用的集合处理抽象。

没有泛型时，这类库要么写起来很别扭，要么用起来很别扭，最后很难成为大家默认接受的主流风格。

所以这件事其实挺能说明一个更底层的问题：

某些库层抽象之所以成立，不只是因为有人愿意实现它，而是因为语言本身已经把它所需的类型能力和表达方式准备好了。

从这个角度看，`Stream` 不只是 `Java` 的一个 API 设计，而是语言和标准库一起配合出来的一种编程体验。

而 `Go` 在泛型补上之前，很难完整复制这种体验，也不奇怪。

<!-- WEIBO_MEDIA_START -->
## 原微博中的媒体

![](./weibo-4288986514035095-1.jpg)
<!-- WEIBO_MEDIA_END -->
