Golang 표준 라 이브 러 리 Buffer
12634 단어 bufferGogolangGo 표준 라 이브 러 리
Go 표준 라 이브 러 리 Buffer 는 가 변 크기 의 바이트 버퍼 입 니 다. Wirte 와 Read 방법 으로 조작 할 수 있 습 니 다. Go 표준 라 이브 러 리 에서 Buffer 에 관 한 데이터 구 조 를 정의 합 니 다.
type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation.
lastRead readOp // last read operation, so that Unread* can work correctly.
}
// The readOp constants describe the last action performed on
// the buffer, so that UnreadRune and UnreadByte can
// check for invalid usage.
type readOp int
const (
opInvalid readOp = iota // Non-read operation.
opReadRune // Read rune.
opRead // Any other read operation.
)
위 와 같이 Buffer 가 저장 한 데 이 터 는 off 에서 len (buf) 구역 사이 이 고 다른 구역 은 데이터 가 없 으 며 & buf [of] 부터 데 이 터 를 읽 고 & buf [len (buf)] 에서 데 이 터 를 쓸 수 밖 에 없습니다. 또한 메모리 에 대한 여러 번 의 조작 을 피하 기 위해 작은 버퍼 에 대해 Buffer 는 boottstrap 을 정의 하여 여러 번 의 메모리 조작 을 피 할 수 있 습 니 다. runeBytes 의 정의 도 마찬가지 입 니 다.Buffer 에 대한 조작 식별 자 lastRead 도 있 습 니 다.
Buffer 의 흔 한 조작
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
func NewBufferString(s string) *Buffer {
return &Buffer{buf: []byte(s)}
}
초기 화 방법 뉴 버 퍼 는 buf 를 매개 변수 로 Buffer 를 초기 화 합 니 다. Buffer 는 읽 을 수도 있 고 쓸 수도 있 습 니 다. Buffer 를 읽 을 때 buf 는 일정한 데 이 터 를 채 워 야 합 니 다. 쓰 려 면 buf 는 일정한 용량 (capacity) 이 있어 야 합 니 다. 물론 new (Buffer) 를 통 해 Buffer 를 초기 화 할 수도 있 습 니 다.또 다른 방법 뉴 버 프 스 트 링 은 읽 을 수 있 는 버 프 를 하나의 string 으로 초기 화하 고 string 의 내용 으로 버 프 를 채 웁 니 다. func (b *Buffer) Read(p []byte) (n int, err error)
func (b *Buffer) Next(n int) []byte
func (b *Buffer) ReadByte() (c byte, err error)
func (b *Buffer) ReadRune() (r rune, size int, err error)
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error)
func (b *Buffer) readSlice(delim byte) (line []byte, err error)
func (b *Buffer) ReadString(delim byte) (line string, err error)
func (b *Buffer) Write(p []byte) (n int, err error)
func (b *Buffer) WriteString(s string) (n int, err error)
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error)
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error)
func (b *Buffer) WriteByte(c byte) error
func (b *Buffer) WriteRune(r rune) (n int, err error)
다음은 Read, ReadRune, ReadBytes 방법 을 분석 하고 방법 Read 에 대해 주로 세 가지 절 차 를 한다. 첫째, Buffer 가 비어 있 는 지 판단 하고 만약 에 Buffer 를 리 셋 한다.둘째, Buffer 의 buf 데 이 터 를 p 로 복사 하고 off 의 위치 표지 Buffer 의 읽 을 수 있 는 위 치 를 조정 합 니 다.셋째, 읽 기 식별 자 를 opRead 로 설정 합 니 다.func (b *Buffer) Read(p []byte) (n int, err error) {
b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
if len(p) == 0 {
return
}
return 0, io.EOF
}
n = copy(p, b.buf[b.off:])
b.off += n
if n > 0 {
b.lastRead = opRead
}
return
}
방법 ReadRune () 은 Buffer 에서 UTF 8 인 코딩 된 rune 데 이 터 를 읽 는 방법 을 정의 합 니 다. 마찬가지 로 세 가지 절차 가 필요 합 니 다. 첫째, Buffer 가 비어 있 는 지 판단 합 니 다. 만약 에 Buffer 를 리 셋 합 니 다.둘째, 읽 기 조작 자 를 opReadRune 으로 설정 합 니 다.셋째, 읽 을 수 있 는 위치 오 프 의 byte 가 utf 8. Runeself 보다 작 는 지 판단 합 니 다. 만약 에 오 프 의 위 치 를 조정 하고 돌아 갑 니 다.그렇지 않 으 면 Buffer 의 데 이 터 를 rune 으로 디 코딩 하여 off 위 치 를 조정 하고 디 코딩 후의 rune 과 크기 를 되 돌려 줍 니 다.
// ReadRune reads and returns the next UTF-8-encoded
// Unicode code point from the buffer.
// If no bytes are available, the error returned is io.EOF.
// If the bytes are an erroneous UTF-8 encoding, it
// consumes one byte and returns U+FFFD, 1.
func (b *Buffer) ReadRune() (r rune, size int, err error) {
b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
return 0, 0, io.EOF
}
b.lastRead = opReadRune
c := b.buf[b.off]
if c < utf8.RuneSelf {
b.off++
return rune(c), 1, nil
}
r, n := utf8.DecodeRune(b.buf[b.off:])
b.off += n
return r, n, nil
}
방법 ReadBytes (delim byte) 는 Buffer 에서 off 에서 첫 번 째 delim 사이 의 데 이 터 를 읽 고 delim, ReadBytes 를 포함 하여 개인 적 인 방법 readSlice 를 호출 하여 이 루어 집 니 다. readSlice 방법 은 delim 의 위 치 를 먼저 찾 고 존재 하지 않 으 면 off 에서 len (buf) 사이 의 데 이 터 를 되 돌려 줍 니 다. 존재 하면 off 에서 off + location (delim) + 1 사이 의 데 이 터 를 되 돌려 줍 니 다.그 중 하 나 는 delim 을 포함 하기 위해 서 이 며, 마지막 으로 조작 식별 자 를 opRead 로 설정 합 니 다.
// ReadBytes reads until the first occurrence of delim in the input,
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadBytes returns err != nil if and only if the returned data does not end in
// delim.
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
slice, err := b.readSlice(delim)
// return a copy of slice. The buffer's backing array may
// be overwritten by later calls.
line = append(line, slice...)
return
}
// readSlice is like ReadBytes but returns a reference to internal buffer data.
func (b *Buffer) readSlice(delim byte) (line []byte, err error) {
i := IndexByte(b.buf[b.off:], delim)
end := b.off + i + 1
if i < 0 {
end = len(b.buf)
err = io.EOF
}
line = b.buf[b.off:end]
b.off = end
b.lastRead = opRead
return line, err
}
마찬가지 로 해당 하 는 Write, Write Rune, ReadFrom, Write To 쓰기 방법 을 분석 하고 방법 Write, 상대 적 으로 Read 방법 에 있어 서 는 Buffer 공간 을 확장 한 다음 에 p 의 데 이 터 를 Buffer 로 복사 해 야 합 니 다.
// Write appends the contents of p to the buffer, growing the buffer as
// needed. The return value n is the length of p; err is always nil. If the
// buffer becomes too large, Write will panic with ErrTooLarge.
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(p))
return copy(b.buf[m:], p), nil
}
방법 WriteRune 에 대해 서 는 먼저 쓸 데이터 rune 이 utf 8 보다 작 는 지 판단 합 니 다. RuneSelf 를 사용 하면 WriteByte 를 사용 하여 Buffer 에 기록 합 니 다. 그렇지 않 으 면 쓸 데이터 rune 을 utf 8 로 인 코딩 하고 Write 를 사용 하여 Buffer 에 기록 합 니 다.
// WriteRune appends the UTF-8 encoding of Unicode code point r to the
// buffer, returning its length and an error, which is always nil but is
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
// if it becomes too large, WriteRune will panic with ErrTooLarge.
func (b *Buffer) WriteRune(r rune) (n int, err error) {
if r < utf8.RuneSelf {
b.WriteByte(byte(r))
return 1, nil
}
n = utf8.EncodeRune(b.runeBytes[0:], r)
b.Write(b.runeBytes[0:n])
return n, nil
}
ReadFrom 방법 은 io. Reader 또는 io. Reader 인 터 페 이 스 를 실현 하 는 인 스 턴 스 에서 모든 데 이 터 를 Buffer 로 읽 습 니 다. 기본적으로 512 바이트 이상 을 읽 습 니 다. Buffer 공간 이 512 가 되 지 않 으 면 Buffer 공간 을 늘 려 야 합 니 다. 이 방법 은 읽 은 바이트 수 와 오류 정 보 를 되 돌려 줍 니 다.ReadFrom 에서 Buffer 가 비어 있 는 지 먼저 판단 하고 비어 있 으 면 Buffer 를 리 셋 합 니 다.그 다음으로 Buffer 의 free 공간 이 충분 한 지 판단 합 니 다. 512 보다 작고 of + free 가 512 보다 작 으 면 Buffer 가 0 에서 off 사이 의 공간 이 부족 하여 현재 Buffer 에서 읽 지 않 은 데이터 의 크기 를 저장 할 수 있 음 을 나타 냅 니 다. 이때 임시 버퍼 를 설정 하고 그 공간 Buffer 의 2 배 에 MinRead (512) 의 공간 을 더 하여 원래 Buffer 의 데 이 터 를 임시 버퍼 로 복사 합 니 다.그 다음 에 임시 버퍼 의 데 이 터 를 원본 Buffer 로 복사 하고 마지막 으로 io. Reader 의 Read 방법 으로 io. Reader 에서 데 이 터 를 읽 습 니 다. io. EOF 를 만 날 때 까지.
// ReadFrom reads data from r until EOF and appends it to the buffer, growing
// the buffer as needed. The return value n is the number of bytes read. Any
// error except io.EOF encountered during the read is also returned. If the
// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
b.lastRead = opInvalid
// If buffer is empty, reset to recover space.
if b.off >= len(b.buf) {
b.Truncate(0)
}
for {
if free := cap(b.buf) - len(b.buf); free < MinRead {
// not enough space at end
newBuf := b.buf
if b.off+free < MinRead {
// not enough space using beginning of buffer;
// double buffer capacity
newBuf = makeSlice(2*cap(b.buf) + MinRead)
}
copy(newBuf, b.buf[b.off:])
b.buf = newBuf[:len(b.buf)-b.off]
b.off = 0
}
m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
b.buf = b.buf[0 : len(b.buf)+m]
n += int64(m)
if e == io.EOF {
break
}
if e != nil {
return n, e
}
}
return n, nil // err is EOF, so return nil explicitly
}
ReadFrom 방법 에 비해 WriteTo 방법 은 간단 합 니 다. WriteTo 는 Buffer 의 데 이 터 를 io. Writer 에 기록 하고 Buffer 에 데이터 가 없 을 때 까지 Buffer 가 비어 있 을 때 Buffer 를 리 셋 하고 되 돌려 줍 니 다.
// WriteTo writes data to w until the buffer is drained or an error occurs.
// The return value n is the number of bytes written; it always fits into an
// int, but it is int64 to match the io.WriterTo interface. Any error
// encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
b.lastRead = opInvalid
if b.off < len(b.buf) {
nBytes := b.Len()
m, e := w.Write(b.buf[b.off:])
if m > nBytes {
panic("bytes.Buffer.WriteTo: invalid Write count")
}
b.off += m
n = int64(m)
if e != nil {
return n, e
}
// all bytes should have been written, by definition of
// Write method in io.Writer
if m != nBytes {
return n, io.ErrShortWrite
}
}
// Buffer is now empty; reset.
b.Truncate(0)
return
}
3. 공간 확장 및 리 셋
Buffer 의 리 셋 방법 Reset () 은 Truncate (n int) 방법 을 호출 하여 Buffer 의 데 이 터 를 제거 합 니 다. Truncate 는 off 에서 시작 한 n 개의 읽 지 않 은 데 이 터 를 제외 한 모든 데 이 터 를 버 리 고 n 이 0 이면 Buffer 를 리 셋 합 니 다.
// Truncate discards all but the first n unread bytes from the buffer.
// It panics if n is negative or greater than the length of the buffer.
func (b *Buffer) Truncate(n int) {
b.lastRead = opInvalid
switch {
case n < 0 || n > b.Len():
panic("bytes.Buffer: truncation out of range")
case n == 0:
// Reuse buffer space.
b.off = 0
}
b.buf = b.buf[0 : b.off+n]
}
// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset() { b.Truncate(0) }
Buffer 에 데 이 터 를 쓸 때 모든 데 이 터 를 Buffer 에 쓸 수 있 도록 공간 을 확장 해 야 합 니 다. Buffer 는 Grow (n int) 방법 으로 Buffer 공간 을 확장 하 는 기능 을 실현 합 니 다. 이 방법 은 개인 적 인 방법 grow (n int) 를 호출 합 니 다.
// grow grows the buffer to guarantee space for n more bytes.
// It returns the index where bytes should be written.
// If the buffer can't grow it will panic with ErrTooLarge.
func (b *Buffer) grow(n int) int {
m := b.Len()
// Buffer , Buffer
if m == 0 && b.off != 0 {
b.Truncate(0)
}
// n Buffer
if len(b.buf)+n > cap(b.buf) {
// buf
var buf []byte
//Buffer buf , , n bootstrap ,
// boostrap buf 。
if b.buf == nil && n <= len(b.bootstrap) {
buf = b.bootstrap[0:]
// , b.buf slice , b.buf buf。
} else if m+n <= cap(b.buf)/2 {
copy(b.buf[:], b.buf[b.off:])
buf = b.buf[:m]
} else {
// ,
buf = makeSlice(2*cap(b.buf) + n)
copy(buf, b.buf[b.off:])
}
b.buf = buf
b.off = 0
}
// n ,
b.buf = b.buf[0 : b.off+m+n]
return b.off + m
}
// Grow grows the buffer's capacity, if necessary, to guarantee space for
// another n bytes. After Grow(n), at least n bytes can be written to the
// buffer without another allocation.
// If n is negative, Grow will panic.
// If the buffer can't grow it will panic with ErrTooLarge.
func (b *Buffer) Grow(n int) {
if n < 0 {
panic("bytes.Buffer.Grow: negative count")
}
m := b.grow(n)
b.buf = b.buf[0:m]
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
존재하는 파일에 데이터 쓰기프로젝트에서 서버를 통해 파일을 전송하는 문제가 발생했습니다. 구체적인 과정: 1. 현재 파일 크기에 따라 하드디스크에 충분한 공간이 있는지 판단한다. 2, 파일 크기에 따라 빈 파일을 만들어서 이 공간을 차지한다....
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.