Skip to content

Commit 4981879

Browse files
committed
How to design I/O API
1 parent 05827e2 commit 4981879

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/posts/Stream.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,52 @@ int main() {
154154
```
155155

156156
关于 JavaScript 中的 `ReadableStream``WriteableStream` 也是同样的,它们本身就是可缓冲的。
157+
158+
## I/O 库的设计
159+
160+
Deno 2.0 中将 1.0 命名空间中 `Reader``Writer` 等接口迁移到了标准库中,但是诸如 `Seeker` 等接口还是保留在了命名空间中,但是实际上 `FsFile` 这类方法已经确实实现了 `Reader``Writer` 等接口,这种迁移之后有巨大的割裂感,参考:<https://github.com/denoland/deno/blob/5683ca40707ae98bba6b58c710b9ff31e9f41944/cli/tsc/dts/lib.deno.ns.d.ts#L2312-L2321>
161+
162+
但是 Deno 中设计 I/O 接口的整体思路和 Golang 十分相似,或者就是直接照搬过来,下面来学习一下:
163+
164+
```ts
165+
// Reader
166+
export interface Reader {
167+
read(p: Uint8Array): Promise<number | null>;
168+
}
169+
// Writer
170+
export interface Writer {
171+
write(p: Uint8Array): Promise<number>;
172+
}
173+
// Seeker
174+
export interface Seeker {
175+
seek(offset: number | bigint, whence: SeekMode): Promise<number>;
176+
}
177+
// Closer
178+
export interface Closer {
179+
close(): void;
180+
}
181+
```
182+
183+
然后看一下 Go 中接口的定义:
184+
185+
```go
186+
type Reader interface {
187+
Read(p []byte) (n int, err error)
188+
}
189+
190+
type Writer interface {
191+
Write(p []byte) (n int, err error)
192+
}
193+
194+
type Closer interface {
195+
Close() error
196+
}
197+
198+
type Seeker interface {
199+
Seek(offset int64, whence int) (int64, error)
200+
}
201+
```
202+
203+
Rust 中的 trait 相比较于 Go 和 Deno 更加复杂一点,虽然在实现 `Reader` 等 trait 的时候只要实现其中的 `read` 方法,但是 trait 中有一系列相关的方法都以提前实现好,只要实现了该 trait 之后,就可以实现这类方法。而 Deno 中更简洁,类似于 Go,这一系列方法都要自己实现:<https://github.com/denoland/deno/blob/5683ca40707ae98bba6b58c710b9ff31e9f41944/ext/fs/30_fs.js#L659-L804>
204+
205+
相较于 Go 和 Rust,它们的文件句柄都稍微复杂,由于多线程可能产生数据竞争,它们往往都需要加锁,而 Deno 更加简单一点。

0 commit comments

Comments
 (0)