Показаны сообщения с ярлыком Пакет io в Golang. Показать все сообщения
Показаны сообщения с ярлыком Пакет io в Golang. Показать все сообщения

суббота, 18 июля 2020 г.

Пакет io в Golang, запись

Функция WriteString

func WriteString(w Writer, s string) (n int, err error)

WriteString записывает содержимое строки s в w, которая принимает часть байтов. Если w реализует StringWriter, его метод WriteString вызывается напрямую. В противном случае w.Write вызывается ровно один раз.

package main

import (
    "io"
    "os"
)

func main() {
    io.WriteString(os.Stdout, "Hello World")

}

Вывод:

Hello World

Интерфейс Writer

Writer - это интерфейс, который оборачивает базовый метод Write.

type Writer interface {
    Write(p []byte) (n int, err error)
}

Write записывает len(p) байтов из p в подлежащий поток данных. Он возвращает количество байтов, записанных из p (0 <= n <= len(p)), и любую обнаруженную ошибку, которая привела к преждевременной остановке записи. Write должен возвращать ошибку, отличную от nil, если он возвращает n < len(p). Write не должен изменять данные среза, даже временно.

Реализации не должны сохранять p.

Функция MultiWriter

func MultiWriter(writers ...Writer) Writer

MultiWriter создает writer, который дублирует свои записи всем предоставленным writer, аналогично команде Unix tee(1).

Каждая запись пишется каждому из перечисленных writer по одному. Если перечисленный writer возвращает ошибку, эта операция записи останавливается и возвращает ошибку; это не продолжается вниз по списку.

package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")

    var buf1, buf2 bytes.Buffer
    w := io.MultiWriter(&buf1, &buf2)

    if _, err := io.Copy(w, r); err != nil {
        log.Fatal(err)
    }

    fmt.Print(buf1.String())
    fmt.Print(buf2.String())

}

Вывод:

some io.Reader stream to be read
some io.Reader stream to be read


Читайте также:


пятница, 17 июля 2020 г.

Пакет io в Golang, функции чтения

Функция ReadAtLeast

func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)

ReadAtLeast читает из r в buf, пока не прочитает хотя бы min байтов. Он возвращает количество скопированных байтов и ошибку, если было прочитано меньше байтов. Ошибка EOF, только если не было прочитано ни одного байта. Если EOF происходит после считывания менее чем min байтов, ReadAtLeast возвращает ErrUnexpectedEOF. Если min больше, чем длина буфера, ReadAtLeast возвращает ErrShortBuffer. По возвращении n >= min, только если err == nil. Если r возвращает ошибку, прочитав хотя бы min байтов, ошибка сбрасывается.

package main

import (
    "fmt"
    "io"
    "log"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")

    buf := make([]byte, 14)
    if _, err := io.ReadAtLeast(r, buf, 4); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", buf)

    // буфер меньше минимального размера чтения.
    shortBuf := make([]byte, 3)
    if _, err := io.ReadAtLeast(r, shortBuf, 4); err != nil {
        fmt.Println("error:", err)
    }

    // минимальный размер чтения больше, чем поток io.Reader
    longBuf := make([]byte, 64)
    if _, err := io.ReadAtLeast(r, longBuf, 64); err != nil {
        fmt.Println("error:", err)
    }

}

Вывод:

some io.Reader
error: short buffer
error: unexpected EOF

Функция ReadFull

func ReadFull(r Reader, buf []byte) (n int, err error)

ReadFull читает точно len(buf) байтов из r в buf. Он возвращает количество скопированных байтов и ошибку, если было прочитано меньше байтов. Ошибка EOF, только если не было прочитано ни одного байта. Если EOF происходит после чтения некоторых, но не всех байтов, ReadFull возвращает ErrUnexpectedEOF. По возвращении n == len(buf) только тогда, когда err == nil. Если r возвращает ошибку, прочитав по крайней мере len(buf) байтов, ошибка сбрасывается.

package main

import (
    "fmt"
    "io"
    "log"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")

    buf := make([]byte, 4)
    if _, err := io.ReadFull(r, buf); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", buf)

    // минимальный размер чтения больше, чем поток io.Reader
    longBuf := make([]byte, 64)
    if _, err := io.ReadFull(r, longBuf); err != nil {
        fmt.Println("error:", err)
    }

}

Вывод:

some
error: unexpected EOF

Тип Reader

Reader - это интерфейс, который оборачивает базовый метод Read.

type Reader interface {
    Read(p []byte) (n int, err error)
}

Read читает до len(p) байтов в p. Он возвращает количество прочитанных байтов (0 <= n <= len(p)) и обнаруженную ошибку. Даже если Read возвращает n < len(p), он может использовать все p как пустое место во время вызова. Если некоторые данные доступны, но не len(p) байтов, Read обычно возвращает то, что доступно, вместо ожидания большего.

Когда Read успешно обнаруживает ошибку или условие конца файла после успешного чтения n > 0 байтов, он возвращает количество прочитанных байтов. Он может вернуть (не nil) ошибку из того же вызова или вернуть ошибку (и n == 0) из последующего вызова. Примером этого общего случая является то, что Reader, возвращающий ненулевое число байтов в конце входного потока, может вернуть либо err == EOF, либо err == nil. Следующее чтение должно вернуть 0, EOF.

Вызывающие всегда должны обрабатывать n > 0 байтов, возвращенных до рассмотрения ошибки err. Это правильно обрабатывает ошибки ввода-вывода, возникающие после чтения некоторых байтов, а также обоих разрешенных вариантов поведения EOF.

Реализации Read не рекомендуется возвращать счетчик нулевых байтов с ошибкой nil, кроме случаев, когда len(p) == 0. Вызывающие операторы должны обрабатывать возврат 0 и nil как указание того, что ничего не произошло; в частности это не указывает на EOF.

Реализации не должны сохранять p (входной срез байтов).

Функция LimitReader

func LimitReader(r Reader, n int64) Reader

LimitReader возвращает Reader, который читает из r, но останавливается с EOF после n байтов. Базовой реализацией является *LimitedReader.

package main

import (
    "io"
    "log"
    "os"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")
    lr := io.LimitReader(r, 4)

    if _, err := io.Copy(os.Stdout, lr); err != nil {
        log.Fatal(err)
    }

}

Вывод:

some

Функция MultiReader

func MultiReader(readers ...Reader) Reader

MultiReader возвращает Reader, который является логическим объединением предоставленных входных считывателей. Они читаются последовательно. Как только все входы вернут EOF, Read вернет EOF. Если кто-либо из читателей вернет ошибку, отличную от nil, не EOF, Read вернет эту ошибку.

package main

import (
    "io"
    "log"
    "os"
    "strings"
)

func main() {
    r1 := strings.NewReader("first reader ")
    r2 := strings.NewReader("second reader ")
    r3 := strings.NewReader("third reader\n")
    r := io.MultiReader(r1, r2, r3)

    if _, err := io.Copy(os.Stdout, r); err != nil {
        log.Fatal(err)
    }

}

Вывод:

first reader second reader third reader

Функция TeeReader

func TeeReader(r Reader, w Writer) Reader

TeeReader возвращает Reader, который пишет в w то, что он читает из r. Все чтения из r, выполненные через него, сопоставляются с соответствующими записями в w. Внутренняя буферизация отсутствует - запись должна завершиться до завершения чтения. Любая ошибка, обнаруженная во время записи, сообщается как ошибка чтения.

package main

import (
    "bytes"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")
    var buf bytes.Buffer
    tee := io.TeeReader(r, &buf)

    printall := func(r io.Reader) {
        b, err := ioutil.ReadAll(r)
        if err != nil {
            log.Fatal(err)
        }

        fmt.Printf("%s", b)
    }

    printall(tee)
    printall(&buf)

}

Вывод:

some io.Reader stream to be read
some io.Reader stream to be read


Читайте также:


четверг, 16 июля 2020 г.

Пакет io в Golang, функция Pipe

func Pipe() (*PipeReader, *PipeWriter)

Pipe создает синхронный pipe в памяти. Его можно использовать для соединения кода, ожидающего io.Reader, с кодом, ожидающим io.Writer.

Чтения и записи в pipe сопоставляются один к одному, за исключением случаев, когда для чтения одной записи требуется несколько операций чтения. То есть каждый Write в PipeWriter блокируется до тех пор, пока не будет выполнено одна или несколько операций Read из PipeReader, которые полностью используют записанные данные. Данные копируются непосредственно из Write в соответствующие Read (или несколько Read); нет внутренней буферизации.

Безопасно вызывать Read и Write параллельно друг с другом или с помощью Close. Параллельные вызовы на чтение и параллельные вызовы на запись также безопасны: индивидуальные вызовы будут проходить последовательно.

package main

import (
    "bytes"
    "fmt"
    "io"
)

func main() {
    r, w := io.Pipe()

    go func() {
        fmt.Fprint(w, "some text to be read\n")
        w.Close()
    }()

    buf := new(bytes.Buffer)
    buf.ReadFrom(r)
    fmt.Print(buf.String())

}

Вывод:

some text to be read

Тип PipeReader

PipeReader - это считывающая половина pipe.

type PipeReader struct {
    // содержит отфильтрованные или неэкспортированные поля
}

func (r *PipeReader) Close() error

Close закрывает reader; последующие записи в записывающей половине pipe будут возвращать ошибку ErrClosedPipe.

func (r *PipeReader) CloseWithError(err error) error

CloseWithError закрывает reader; последующие записи в записывающей половине pipe будут возвращать err.

CloseWithError никогда не перезаписывает предыдущую ошибку, если она существует, и всегда возвращает nil.

func (r *PipeReader) Read(data []byte) (n int, err error)

Read реализует стандартный интерфейс Read: он читает данные из pipe, блокируя до тех пор, пока не прибудет writer или не закроется конец записи. Если конец записи закрыт с ошибкой, эта ошибка возвращается как err; в противном случае ошибка EOF.

Тип PipeWriter

PipeWriter - это записывающая половина pipe.

type PipeWriter struct {
    // содержит отфильтрованные или неэкспортированные поля
}

func (w *PipeWriter) Close() error

Close закрывает writer; последующие чтения из считывающей половины pipe не будут возвращать байты и вернут EOF.

func (w *PipeWriter) CloseWithError(err error) error

CloseWithError закрывает writer; последующие операции чтения из считывающей половины pipe не будут возвращать байтов и вернут ошибку err, или EOF, если err равно nil.

CloseWithError никогда не перезаписывает предыдущую ошибку, если она существует, и всегда возвращает nil.

func (w *PipeWriter) Write(data []byte) (n int, err error)

Write реализует стандартный интерфейс Write: он записывает данные в pipe, блокируя до тех пор, пока один или несколько считывателей не израсходуют все данные или не будет закрыт конец чтения. Если конец чтения закрыт с ошибкой, эта err возвращается как err; в противном случае ошибка - ErrClosedPipe.


Читайте также:


среда, 15 июля 2020 г.

Пакет io в Golang, функции копирования

Функция Copy

func Copy(dst Writer, src Reader) (written int64, err error)

Copy копирует из src в dst, пока на src не будет достигнут EOF или пока не произойдет ошибка. Возвращает количество скопированных байтов и первую ошибку, обнаруженную при копировании, если таковые имеются.

При успешном копировании возвращается err == nil, а не err == EOF. Поскольку копирование определено для чтения из src до EOF, оно не рассматривает EOF из чтения как ошибку, о которой будет сообщено.

Если src реализует интерфейс WriterTo, копия реализуется путем вызова src.WriteTo(dst). В противном случае, если dst реализует интерфейс ReaderFrom, копия реализуется путем вызова dst.ReadFrom(src).

package main

import (
    "io"
    "log"
    "os"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")

    if _, err := io.Copy(os.Stdout, r); err != nil {
        log.Fatal(err)
    }

}

Вывод:

some io.Reader stream to be read

Функция CopyBuffer

func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)

CopyBuffer идентичен Copy, за исключением того, что он поэтапно использует предоставленный буфер (если он необходим), а не выделяет временный. Если buf равен nil, выделяется один новый; в противном случае, если он имеет нулевую длину, CopyBuffer паникует.

Если src реализует WriterTo или dst реализует ReaderFrom, buf не будет использоваться для выполнения копирования.

package main

import (
    "io"
    "log"
    "os"
    "strings"
)

func main() {
    r1 := strings.NewReader("first reader\n")
    r2 := strings.NewReader("second reader\n")
    buf := make([]byte, 8)

    // buf используется здесь...
    if _, err := io.CopyBuffer(os.Stdout, r1, buf); err != nil {
        log.Fatal(err)
    }

    // ... переиспользуется также здесь. 
    // Нет необходимости выделять дополнительный буфер.
    if _, err := io.CopyBuffer(os.Stdout, r2, buf); err != nil {
        log.Fatal(err)
    }

}

Вывод:

first reader
second reader

Функция CopyN

func CopyN(dst Writer, src Reader, n int64) (written int64, err error)

CopyN копирует n байтов (или до ошибки) из src в dst. Возвращает количество скопированных байтов и самую раннюю ошибку, возникшую при копировании. По возвращении written == n только тогда, когда err == nil.

Если dst реализует интерфейс ReaderFrom, копия реализуется с его помощью.

package main

import (
    "io"
    "log"
    "os"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read")

    if _, err := io.CopyN(os.Stdout, r, 5); err != nil {
        log.Fatal(err)
    }

}

Вывод:

some 


Читайте также:


Пакет io в Golang, ошибки

Пакет io предоставляет базовые интерфейсы для примитивов ввода/вывода. Его основная задача заключается в том, чтобы обернуть существующие реализации таких примитивов, таких как в пакете os, в общие открытые интерфейсы, которые абстрагируют функциональность, а также некоторые другие связанные примитивы.

Поскольку эти интерфейсы и примитивы обертывают низкоуровневые операции различными реализациями, если не сообщено обратное клиенты должны предполагать, что они небезопасны для параллельного выполнения.

Переменные в пакете io

EOF - это ошибка, возвращаемая Read, когда больше нет доступных входных данных. Функции должны возвращать EOF только для того, чтобы сигнализировать о постепенном завершении ввода. Если EOF неожиданно возникает в потоке структурированных данных, соответствующей ошибкой является либо ErrUnexpectedEOF, либо какая-либо другая ошибка, дающая более подробную информацию.

var EOF = errors.New("EOF")

ErrClosedPipe - это ошибка, используемая для операций чтения или записи в закрытом gfqgt.

var ErrClosedPipe = errors.New("io: read/write on closed pipe")

ErrNoProgress возвращается некоторыми клиентами io.Reader, когда многие вызовы Read не смогли вернуть какие-либо данные или ошибки, как правило, признак неправильной реализации io.Reader.

var ErrNoProgress = errors.New("multiple Read calls return no data or error")

ErrShortBuffer означает, что для чтения требовался более длинный буфер, чем было предоставлено.

var ErrShortBuffer = errors.New("short buffer")

ErrShortWrite означает, что запись приняла меньше байтов, чем запрошено, но не смогла вернуть явную ошибку.

var ErrShortWrite = errors.New("short write")

ErrUnexpectedEOF означает, что EOF был обнаружен в середине чтения блока фиксированного размера или структуры данных.

var ErrUnexpectedEOF = errors.New("unexpected EOF")


Читайте также: