[GO] #3-9. 패키지 탐방 (bufio, index/suffixarray, embed)

Study·2021년 6월 9일
0

고랭

목록 보기
16/18
post-thumbnail

bufio

bufio 는 버퍼링된 I/O 를 구현한다.

io.Reader 또는 io.Writer 객체를 래핑하여 인터페이스를 구현하지만 버퍼링 및 텍스트 I/O 에 대한 도움을 제공하는 다른 개체를 만든다.

상수

const (
	// 토큰을 버퍼링하는데 최대 크기
	MaxScanTokenSize = 64 * 1024
)

변수

var (
    ErrInvalidUnreadByte = errors.New("bufio: invalid use of UnreadByte")
    ErrInvalidUnreadRune = errors.New("bufio: invalid use of UnreadRune")
    ErrBufferFull        = errors.New("bufio: buffer full")
    ErrNegativeCount     = errors.New("bufio: negative count")
    ErrTooLong         = errors.New("bufio.Scanner: token too long")
    ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")
    ErrAdvanceTooFar   = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
    ErrBadReadCount    = errors.New("bufio.Scanner: Read returned impossible count")
)

다음은 특수한 감시 오류 값이다.

오류와 함께 전달되는 토큰이 마지막 토큰이고 이 노큰 이후에 스캔이 중지되어야 함을 나타내기 위해 Split 함수에 의해 반환된다.

Scan 에서 ErrFinalToken 을 수신하면 오류없이 검색이 중지된다.

이 값은 처리를 조기에 중지하거나 최종 빈 토큰을 전달해야할 때 유용하다.

var ErrFinalToken = errors.New("final token")

함수

func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)

각 바이트를 토큰으로 반환하는 스캐너의 분할 함수이다.

func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)

후행 줄 끝 마커를 제거하고 각 텍스트 줄을 반환하는 스캐너 용 분할 기능이다.

반환된 줄은 비어있을 수 있다.

func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)

각 UTF-8로 인코딩된 룬을 토큰으로 반환하는 스캐너의 분할 함수이다.

반환된 룬의 시퀀스는 입력에 대한 범위 루프의 문자열과 동일하다.

func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)

주변 공백이 삭제된 상태에서 각 공백으로 구분된 텍스트 단어를 반환하는 Scanner 용 분할 기능이다.

빈 문자열을 반환하지 않는다.

타입

ReadWriter

type ReadWriter struct {
	*Reader
    *Writer
}

ReadWriterReaderWriter 에 대한 포인터를 저장한다.

io.ReadWriter 를 구현한다.

func NewReadWriter(r *Reader, w *Writer) *ReadWriter

rw 를 디스패치하는 새로운 ReadWriter 를 할당한다.

Reader

type Reader struct {
	// 필터링되거나 내보내지지 않은 필드 포함
}

io.Reader 객체에 대한 버퍼링을 구현한다.

func NewReader(rd io.Reader) *Reader

버퍼가 기본 사이즈인 새로운 Reader 를 반환한다.

func NewReaderSize(rd io.Reader, size int) *Reader

버퍼가 지정된 크기 이상인 새 Reader 를 반환한다.

인수 io.Reader 가 이미 충분히 큰 Reader 인 경우 기본 Reader 를 반환한다.

func (b *Reader) Buffered() int

현재 버퍼에서 읽을 수 있는 바이트 수를 반환한다.

func (b *Reader) Discard(n int) (discarded int, err error)

다음 n 바이트를 건너 뛰고 폐기된 바이트 수를 반환한다.

Discard 가 n 바이트 미만을 건너 뛰면 오류도 반환된다.

0 <= n <= b.Buffered() 이면 기본 io.Reader 에서 읽지 않고도 Discard 가 성공할 수 있다.

func (b *Reader) Peek(n int) ([]byte, error)

판독기를 진행하지 않고 다음 n 바이트를 반환한다.

바이트는 다음 읽기 호출에서 유효하지 않고 n 바이트 미만을 반환하면 읽기가 짧은 이유를 설명하는 오류도 반환된다.

nb 버퍼 크기보다 크면 오류는 ErrBufferFull 이다.

func (b *Reader) Read(p []byte) (int, error)

데이터 p 를 읽어 바이트 수를 반환한다.

최대 한 번의 읽기에서 가져오므로 nlen(p) 보다 작을 수 있다.
정확시 len(p) 바이트를 읽으려면 io.ReadFull(b, p) 를 사용하자.

EOF 에서 카운트는 0 이 되고 err 은 io.EOF 가 된다.

func (b *Reader) ReadByte() (byte, error)

단일 바이트를 읽고 반환한다.

사용 가능한 바이트가 없으면 오류를 반환한다.

func (b *Reader) ReadBytes(delim byte) ([]byte, error)

입력에서 delim 이 처음 나타날 때까지 읽고 구분 기호까지 포함한 데이터를 포함하는 슬라이스를 반환한다.

구분 기호 찾기 전에 오류가 발생하면 이전에 읽은 데이터와 오류 자체를 반환한다.

delim 으로 끝나지 않는 경우만 err != nil 을 반환한다.

간단한 사용에서는 스캐너가 더 편할 수 있다.

func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)

낮은 수준의 라인 읽기 기본요소이다. 대부분의 호출자 ReadByte('\n') 또는 ReadString('\n') 을 사용하거나 스캐너를 사용해야 한다.

라인이 버퍼에 비해 너무 길면 isPrefix 가 설정되고 라인의 시작 부분이 반환된다. 나머지 라인은 향후에 반환된다.

라인 마지막 조각을 반환할때는 false 가 된다.
끝에서 반환된 텍스트에는 \r\n \n 는 포함되지 않는다.

func (b *Reader) ReadRune() (r rune, size int, err error)

UTF-8 로 인코딩된 단일 유니 코드 문자를 읽고 룬과 해당 크기를 바이트 단위로 반환한다.

인코딩된 룬이 유효하지 않은 경우 1 바이트를 소비하고 크기가 1 인 unicode.ReplacementChar 를 반환한다.

func (b *Reader) ReadSlice(delim byte) (line []byte, err error)

delim 이 처음 나타날 때까지 읽고 버퍼의 바이트를 가리키는 슬라이스를 반환한다. 바이트는 다음 읽기에서 유효하지 않다.

구분 기호를 찾기 전에 오류가 발생하면 버퍼의 모든 데이터와 오류 자체를 반환한다.

버퍼가 delim 없이 채워지면 ErrBufferFull 과 함께 실패한다.

func (b *Reader) ReadString (delim byte) (string ,error)

입력에서 delim 이 처음 나타날 때까지 읽고 구분 기호까지 포함하는 데이터를 포함할 문자열을 반환한다.

구분 기호를 찾기 전에 ReadString 에 오류가 발생하면 이전에 읽은 데이터와 오류 자체를 반환한다.

delim 으로 끝나지 않는 경우에만 err != nil 을 반환한다

간단한 사용엔 스캐너가 더 편리하다.

func (b *Reader) Reset(r io.Reader)

버퍼링된 데이터를 버리고 모든 상태를 재설정하며 판독기를 r 에서 읽도록 전환한다.

func (b *Reader) Size() int

기본 버퍼의 크기를 바이트 단위로 반환한다.

func (b *Reader) UnreadByte() error

마지막 바이트를 읽지 않는다.

가장 최근에 읽은 바이트만 읽지 않을 수도 있다.

func (b *Reader) UnreadRune() error

마지막 룬을 읽지 않는다.

Reader 에서 가장 최근에 호출된 메소드가 ReadRune 이 아닌 경우 UnreadRune 은 오류를 반환한다.

func (b *Reader) WriteTo(w io.Writer) (n int64, err error)

io.WriterTo 를 구현한다.

기본 Reader 의 Read 메소드를 여러번 호출할 수 있다.

Scanner

type Scanner struct {
	// 필터링되거나 내보내지지 않은 필드 포함
}

줄 바꿈으로 구분된 텍스트 파일과 같은 데이터를 읽기 위한 편리한 인터페이스를 제공한다.

Scan 메소드에 대한 연속 호출은 토큰 사이의 바이트를 건너 뛰고 파일의 '토큰' 을 통과한다.

토큰 사양은 SplitFunc 유형의 분할 함수에 의해 정의된다.

스캔은 EOF, 첫 번째 I/O 오류 또는 너무 큰 버퍼라 맞지 않는 토큰에서 복구 불가능하게 중지된다.

오류 처리 또는 큰 토큰에 대한 더 많은 제어가 필요하거나 판독기에서 순차적 스캔을 실행해야하는 프로그램은 bufio.Reader 를 사용하자.

func (s *Scanner) Buffer(buf []byte, max int)

버퍼는 스캔할 때 사용할 초기 버퍼와 스캔 중에 할당할 수 있는 버퍼의 최대 크기를 설정한다.

최대 토큰 크기는 max 및 cap(buf) 보다 크다.

max <= cap(buf) 이면 Scan 은 이 버퍼만 사용하고 할당하지 않는다.

기본적으로 Scan 은 내부 버퍼를 사용하고 최대 토큰 크기를 MaxScanTokenSize 로 설정한다.

스캰 시작 후 호출되면 패닉이 발생한다.

func (s *Scanner) Bytes() []byte

Scan 호출에 의해 생성된 가장 최근 토큰을 반환한다.

기본 배열은 Scan 에 대한 후속 호출에서 덮어 쓸 데이터를 가리킬 수 있다.

func (s *Scanner) Err() error

스캐너에서 발생한 첫 번째 비 EOF 오류를 반환한다.

func (s *Scanner) Scan() bool

스캐너를 다음 토큰으로 진행한 다음 바이트 또는 텍스트 방법을 통해 사용할 수 있다.

입력의 끝에 도달하거나 오류가 발생하여 스캔이 중지되면 false 를 리턴한다.

Scan 이 false 를 반환하면 Err 메소드는 스캔 중 발생한 모든 오류를 반환한다.

단, io.EOF 이면 Err 은 nil 을 반환한다.

Split 함수가 입력을 진행하지 않고 너무 많은 빈 토큰을 반환하면 패닉을 스캔한다. 이때는 스캐너의 일반적인 오류 모드이다.

func (s *Scanner) Split(split SplitFunc)

스캐너의 분할 기능을 설정한다. 기본 분할 기능은 ScanLines 이다.

스캔 시작 후 호출되면 분할 패닉이 발생한다.

func (s *Scanner) Text() string

Scan 호출에 의해 생성된 가장 최근 토큰을 새당 바이트를 포함하는 할당된 문자열로 반환한다.

SplitFunc

type SplitFunc func (data [] byte , atEOF bool ) 
	(advance int , token [] byte , err error )

입력을 토큰화 하는데 사용되는 분할 함수이다.
인수는 처리되지 않은 나머지 데이터의 초기 하위 문자열과 독자에게 더 이상 제공할 데이터가 없는지 여부를 반환하는 플래그 atEOF 이다.

반환 값은 입력을 진행할 바이트 수와 사용자에게 반환할 다음 토큰 및 오류이다.

함수가 오류를 반환하면 스캔이 중지되며, 이 경우 일부 입력이 삭제될 수 있다.

그렇지 않으면 스캐너가 입력을 진행하고, 토큰이 nil 이 아니면 스캐너는 토큰을 사용자에게 반환한다.

토큰이 nil 이면 스캐너는 더 많은 데이터를 읽고 스캔을 계속한다.

Writer

type Writer struct {
	// 필터링되거나 내보내지지 않은 필드 포함
}

io.Writer 객체에 대한 버퍼링을 구현한다.

모든 데이터가 기록된 후에 클라이언트는 모든 데이터가 기본 io.Writer 로 전달되었는지 확인을 위해 Flush 메소드를 호출해야한다.

func NewWriter(w io.Writer) *Writer

버퍼가 기본 크기인 새 작성기를 반환한다.

func NewWriterSize(w io.Writer, size int) *Writer

버퍼에 최소한 지정된 크기가 있는 새 작성기를 반환한다.

인수 io.Writer 가 이미 충분히 큰 Writer 인 경우 기본 Writer 를 반환한다.

func (b *Writer) Abailable() int

버퍼에서 사용되지 않은 바이트 수를 반환한다.

func (b *Writer) Buffered() int

현재 버퍼에 기록된 바이트 수를 반환한다.

func (b *Writer) Flush() error

버퍼링된 데이터를 기본 io.Writer 에 쓴다.

func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)

io.ReaderFrom 을 구현한다.

작성기가 ReadFrom 메소드를 지원하고 b 에 아직 버퍼링된 데이터가 없을 경우 버퍼링없이 기본 ReadFrom 을 호출한다.

func (b *Writer) Reset(w io.Writer)

플러시되지 않은 버퍼링된 데이터를 버리고 오류를 지운 후 b 를 재설정하여 w 에 출력을 기록한다.

func (b *Writer) Size() int

기본 버퍼의 크기를 바이트 단위로 반환한다.

func (b *Writer) Write(p []byte) (nn int, err error)

p 의 내용을 버퍼에 쓴다. 쓴 바이트 수를 반환한다.

nn < len(p) 이면 쓰기가 짧은 이유를 설명하는 오류도 반환한다.

func (b *Writer) WriteByte(c byte) error

단일 바이트를 쓴다.

func (b *Writer) WriteRun(r rune) (size int, err error)

단일 유니코드 포인트를 작성하여 쓴 바이트 수와 오류를 반환한다.

func (b *Writer) WriteString(s string) (int, error)

문자열을 쓴다.

쓴 바이트 수를 반환하며 개수가 len(s) 보다 작으면 쓰기가 짧은 이류를 설명하는 오류도 반환한다.

index/suffixarray

접미사 배열은 메모리 내 접미사 배열을 사용하여 로그 시간으로 하위 문자열 검색을 구현할 수 있다.

예시

// 일부 데이터에 대한 색인 생성
index := suffixarray.New(data)

// 바이트 슬라이스 조회
offset1 := index.Lookup(s, -1)	// s 가 발생하는 모든 인덱스 목록
offset2 := index.Lookup(s, 3)	// s 가 발생하는 최대 3 개의 인덱스 목록

인덱스는 빠른 하위 문자열 검색을 한다

type Index struct {
	// 필터링되거나 내보내지지 않은 필드 포함
}
func New(data []byte) *Index

데이터에 대한 새 색인을 만든다.

인덱스 생성 시간은 N = len(data) 에 대해 O(N) 이다.

func (x *Index) Bytes() []byte

인덱스가 생성된 데이터를 반환한다. 수정해서는 안된다.

func (x *Index) FindAllIndex(r *regexp.Regexp, n int)(result [][]int)

정규식 r 의 겹치지 않는 일치 항목의 정렬 목록을 반환한다.

여기서 일치하는 x.Bytes() 조각을 지정하는 인덱스 쌍이다.

func (x *Index) Lookup(s []byte, n int) (result []int)

인덱싱된 데이터에서 바이트 문자열 s 가 발생하는 최대 n 인덱스의 정렬되지 않은 목록을 반환한다.

func (x *Index) Read(r io.Reader) error

r 에서 x 로 색인을 읽는다. xnil 이 아니어야 한다.

func (x *Index) Write(w io.Writer) error

인덱스 xw 에 쓴다.

embed

실행중인 GO 프로그램에 포함된 파일에 대한 엑세스를 제공한다.

소스 파일은 //go:embed 지시문을 사용하여 컴파일 타임에 패키지 디렉토리 또는 하위 디렉토리에서 읽은 파일 내용으로 문자열, []byte 도는 FS 유형의 변수를 초기화할 수 있다.

다음과 같은 세 가지 방법이 있다.

  1. 하나의 파일을 문자열에 포함
import _ "embed"

//go:embed hello.txt
var s string
print(s)
  1. 하나의 파일을 바이트 조각에 포함
import _ "embed" 

//go : embed hello.txt 
var b [] byte 
print (string (b))
  1. 파일 시스템에 하나 이상의 파일 포함
import "embed" 

//go : embed hello.txt 
var f embed.FS 
데이터, _ : = f.ReadFile ( "hello.txt") 
print (string (data))

지시어

변수 선언 위에 //go:embed 지시문으로 파일을 지정한다.

지시문은 단일 변수 선언이 포함된 행 바로 앞에 와야한다.
지시문과 선언 사이에 빈 라인과 주석 만 허용된다.

변수 유형은 문자열 유형, 바이트 유형의 슬라이스 또는 FS 여야 한다.

예시

package server

import "embed"

// 정적 웹 서버 콘텐츠를 소유
//go:embed image/* template/*
//go:embed html/index.html
var content embed.FS

GO 빌드 시스템에서 지시문을 인식하고 선언된 변수가 가진 파일 시스템의 일치하는 파일로 채워지도록 정렬한다.

공백으로 구분된 여러 패턴을 허용하지만 패턴이 많을 때 긴 줄을 피하기 위해 반복할 수도 있다.

패턴은 소스 파일이 포함된 패키지 디렉토리를 기준으로 해석된다.
경로 구분 기호는 슬래시이며 . 가 포함될 수 없다. 또는 .. 과 빈 경로 요소, 슬래시로 시작하거나 끝낼 수 없다.

현 디렉토리의 모든 항목을 일치 시키려면 . 대신 * 을 사용하자.

이름에 공백이 있는 파일 이름은 큰 따옴표 또는 역따옴표 문자열 리터럴로 작성할 수 있다.

패턴이 디렉토리 이름을 지정하면 . 로 시작하는 이름을 가진 파일을 제외하고 해당 디렉토리를 루트로 하는 서브 트리의 모든 파일이 임데드 된다.
또는 _ 는 제외한다. 그래서 위 예시는 다음 예시와 거의 같다.

예시

// 정적 웹 서버 콘텐츠 
//go:embed image template html/index.html
var content embed.FS

차이점은 image/*image/.tempfile 을 포함하고 image 는 포함하지 않는다는 것이다.

문자열 및 바이트

string 또는 []byte 유형의 변수에 대한 //go:embed 행은 단일 패턴만 가질 수 있으며 해당 패턴은 단일 파일과 일치할 수 있다.

문자열 또는 []byte 는 해당 파일의 내용으로 초기화된다.

파일 시스템

단일 파일을 포함하려면 문자열 또는 []byte 유형의 변수가 가장 좋다.
FS 유형을 사용하려면 정적 웹 서버 콘텐츠의 디렉토리와 같은 파일 트리를 포함할 수 있다.

FS 는 io/fs 패키지의 FS 인터페이스를 구현하므로 net/http, text/template 및 html/template 를 포함하여 파일 시스템으ㅡㄹ 이해하는 모든 패키지와 함께 사용할 수 있다.

예로 위 예에서 콘텐츠 변수가 주어진다면 다음과 같이 작성할 수 있다.

http.Handle("/static/", 
	http.StripPrefix("/static/", http.FileServer(http.FS(content))))

template.ParseFS(content, "*.tmpl")

도구

GO 패키지를 분석하는 도구를 지원하기 위해 //go:embed 행에 있는 패턴을 go list 출력에서 사용할 수 있다.

type

type FS struct {
	// 필터링되거나 내보내지지 않은 필드 포함
}

FS 는 읽기 전용 파일 모음이며 일반적으로 //go:embed 지시문으로 초기화된다. 지시문 없이 선언하면 FS 는 빈 파일 시스템이다.

FS 는 읽기 전용 값이기 때문에 여러 고루틴에서 동시에 사용하는 것이 안전하며 서로 FS 유형의 값을 할당하는 것도 안전하다.

FS 는 fs.FS 를 구현하므로 net/http, text/template 및 html/template 을 포함하여 파일 시스템 인터페이스를 이해하는 모든 패키지와 함께 사용할 수 있다.

func (f FS) Open(name string) (fs, File, error)

읽기 위해 명명된 파일을 열고 fs.File 을 반환한다.

func (f FS) ReadDir(name string)([]fs, DirEntry, error)

명명된 전체 디렉터리를 읽고 반환한다.

func (f FS) ReadFile(name string) ([]byte, error)

명명된 파일의 내용을 읽고 반환한다.

profile
Study

0개의 댓글