例を通してGoとRust----IO Readerを学ぶ
IO操作は私たちがプログラミングするときによく出会うもので、両方の言語は共通のRead方法を提供しており、reader構造体からデータを読み出すことができます.
Go
go言語であるタイプがインタフェースを実装しているかどうかは,表示されていないことがわかり,関数署名が同じであれば,このインタフェースを実装していると言える.
くりを一つあげる
Rust
Go言語でのコピーとは異なり、ここでreadされると元のデータが修正され、まだreadされていない部分だけが残ります.
栗をもう一つあげる
Go
//io/io.go
type Reader interface {
Read(p []byte) (n int, err error)
}
//bytes/reader.go
type Reader struct {
s []byte
i int64 // current reading index
prevRune int // index of previous rune; or < 0
}
// Read implements the io.Reader interface.
func (r *Reader) Read(b []byte) (n int, err error) {
if r.i >= int64(len(r.s)) {
return 0, io.EOF
}
r.prevRune = -1
n = copy(b, r.s[r.i:])
r.i += int64(n)
return
}
go言語であるタイプがインタフェースを実装しているかどうかは,表示されていないことがわかり,関数署名が同じであれば,このインタフェースを実装していると言える.
a.Read(b)
は、aの中のデータをbにコピーし、aの中の既読座標を修正することを示す.くりを一つあげる
import (
"bytes"
)
func main() {
reader := bytes.NewReader([]byte{1, 2, 3})
target := make([]byte, 5)
fmt.Println(reader, target)
reader.Read(target)
fmt.Println(reader, target)
}
&{[1 2 3] 0 -1} [0 0 0 0 0]
&{[1 2 3] 3 -1} [1 2 3 0 0]
Rust
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result;
impl Read for &[u8] {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result {
let amt = cmp::min(buf.len(), self.len());
let (a, b) = self.split_at(amt);
// First check if the amount of bytes we want to read is small:
// `copy_from_slice` will generally expand to a call to `memcpy`, and
// for a single byte the overhead is significant.
if amt == 1 {
buf[0] = a[0];
} else {
buf[..amt].copy_from_slice(a);
}
*self = b;
Ok(amt)
}
Go言語でのコピーとは異なり、ここでreadされると元のデータが修正され、まだreadされていない部分だけが残ります.
栗をもう一つあげる
use std::io::Read;
fn main() {
let mut reader: &[u8] = &[1, 2, 3][..];
let target: &mut [u8] = &mut [0;5][..];
reader.read(target);
let empty_slice: &[u8] = &[][..];
assert_eq!(reader, empty_slice);
assert_eq!(target, &[1,2,3,0,0]);
}