io.NewOffsetWriter în Go

Creează un Writer care scrie într-o destinație cu acces direct (ca un fișier) începând de la poziția off.

Sintaxă
func NewOffsetWriter(w WriterAt, off int64) *OffsetWriter

Ce face io.NewOffsetWriter

io.NewOffsetWriter primește o destinație care permite scrierea la orice poziție (io.WriterAt, de exemplu *os.File) și returnează un *io.OffsetWriter. Scrierile prin el încep la off și continuă de acolo; poziția proprie se poate muta cu Seek, iar WriteAt scrie relativ la off.

Pentru că folosește WriteAt, nu mută poziția fișierului și mai multe OffsetWriter-e pot scrie în paralel în zone diferite ale aceluiași fișier. Este perechea lui io.NewSectionReader și e utilă la descărcări pe bucăți sau la completarea unor zone fixe dintr-un fișier binar. Pe un fișier deschis cu O_APPEND, WriteAt dă eroare.

Parametri

Parametru Descriere
w Destinația cu acces direct (io.WriterAt).
off Poziția de la care începe scrierea.

Ce returnează

Un *io.OffsetWriter.

Exemple

Exemplul 1: Completarea unui câmp la poziție fixă

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    os.WriteFile("factura.txt", []byte("Factura nr. ______ / 2025"), 0o644)
    f, _ := os.OpenFile("factura.txt", os.O_RDWR, 0)
    defer f.Close()

    w := io.NewOffsetWriter(f, 12)
    fmt.Fprintf(w, "%06d", 1042)

    date, _ := os.ReadFile("factura.txt")
    fmt.Println(string(date))
}

Rezultat

Factura nr. 001042 / 2025

Exemplul 2: Bucăți scrise în paralel, ca la o descărcare

package main

import (
    "fmt"
    "io"
    "os"
    "strings"
    "sync"
)

func main() {
    bucati := []string{"Bună ", "ziua ", "din ", "Iași!"}
    f, _ := os.Create("mesaj.txt")
    defer f.Close()

    var wg sync.WaitGroup
    var poz int64
    for _, b := range bucati {
        start := poz
        poz += int64(len(b))
        wg.Go(func() {
            io.Copy(io.NewOffsetWriter(f, start), strings.NewReader(b))
        })
    }
    wg.Wait()

    date, _ := os.ReadFile("mesaj.txt")
    fmt.Println(string(date))
}

Rezultat

Bună ziua din Iași!

Greșeli frecvente

  • Deschizi fișierul cu O_APPEND: WriteAt nu este permis și scrierea dă eroare.

Comenzi înrudite

  • io.NewSectionReader: Creează un Reader care vede doar o porțiune (de la off, n octeți) dintr-o sursă cu acces direct, ca un fișier.
  • os.File.Seek: Mută poziția curentă de citire/scriere din fișier, față de început, de poziția curentă sau de final.
  • io.Writer: Interfața pentru orice destinație în care se pot scrie octeți: fișiere, ecran, buffer-e, răspunsuri HTTP.