Ce face os.OpenFile
os.OpenFile este funcția generală de deschidere; os.Open și os.Create o apelează cu opțiuni fixe. Al doilea argument combină cu | exact un mod de acces și oricâte opțiuni:
Mod de acces: os.O_RDONLY (doar citire), os.O_WRONLY (doar scriere), os.O_RDWR (ambele). Opțiuni: os.O_CREATE (creează dacă lipsește), os.O_APPEND (fiecare scriere merge la final), os.O_TRUNC (golește la deschidere), os.O_EXCL (împreună cu O_CREATE: eroare dacă fișierul există deja), os.O_SYNC (scriere sincronă pe disc).
perm contează doar când fișierul este creat (de exemplu 0o644, sau 0o600 pentru fișiere private) și se aplică după masca umask. Combinația cea mai des folosită este cea pentru jurnale: os.O_APPEND|os.O_CREATE|os.O_WRONLY.
Parametri
| Parametru | Descriere |
|---|---|
name |
Calea fișierului. |
flag |
Modul de acces și opțiunile, combinate cu |. |
perm |
Drepturile pentru un fișier nou. |
Ce returnează
Fișierul deschis și nil, sau nil și o eroare *fs.PathError.
Exemple
Exemplul 1: Jurnal cu adăugare la final
package main
import (
"fmt"
"os"
)
func scrieJurnal(mesaj string) error {
f, err := os.OpenFile("magazin.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
defer f.Close()
_, err = fmt.Fprintln(f, mesaj)
return err
}
func main() {
scrieJurnal("09:00 deschis")
scrieJurnal("09:12 comanda 1042")
scrieJurnal("09:40 comanda 1043")
date, _ := os.ReadFile("magazin.log")
fmt.Print(string(date))
}
Rezultat
09:00 deschis
09:12 comanda 1042
09:40 comanda 1043
Exemplul 2: Creare exclusivă cu O_EXCL
A doua încercare eșuează, pentru că fișierul există deja. Așa creezi sigur un fișier de blocare sau eviți suprascrierea.
package main
import (
"errors"
"fmt"
"io/fs"
"os"
)
func main() {
for i := 1; i <= 2; i++ {
f, err := os.OpenFile("factura-1042.pdf", os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o644)
if errors.Is(err, fs.ErrExist) {
fmt.Println("încercarea", i, ": factura există deja, nu o suprascriu")
continue
}
fmt.Println("încercarea", i, ": factură creată")
f.Close()
}
}
Rezultat
încercarea 1 : factură creată
încercarea 2 : factura există deja, nu o suprascriu
Exemplul 3: Citire și modificare în același fișier
package main
import (
"fmt"
"io"
"os"
"strconv"
"strings"
)
func main() {
os.WriteFile("contor.txt", []byte("41"), 0o644)
f, err := os.OpenFile("contor.txt", os.O_RDWR, 0)
if err != nil {
fmt.Println("eroare:", err)
return
}
defer f.Close()
date, _ := io.ReadAll(f)
n, _ := strconv.Atoi(strings.TrimSpace(string(date)))
f.Truncate(0)
f.Seek(0, io.SeekStart)
f.WriteString(strconv.Itoa(n + 1))
nou, _ := os.ReadFile("contor.txt")
fmt.Println("vizitatori:", string(nou))
}
Rezultat
vizitatori: 42
Greșeli frecvente
- Uiți modul de acces:
os.OpenFile(n, os.O_APPEND|os.O_CREATE, 0o644)deschide doar pentru citire (O_RDONLYeste 0), iar scrierea dă eroare. Adaugăos.O_WRONLY. - Pui
O_CREATEfărăO_TRUNCși scrii un text mai scurt peste unul mai lung. Rămâne la final o bucată din conținutul vechi. - Dai
permîn zecimal (644). Scrie0o644.
Comenzi înrudite
os.Open: Deschide un fișier existent doar pentru citire și returnează un *os.File.os.Create: Creează un fișier nou (sau golește unul existent) și îl deschide pentru scriere și citire.os.File: Tipul care reprezintă un fișier deschis; îl obții cu os.Open, os.Create sau os.OpenFile.os.IsNotExist: IsNotExist spune dacă o eroare înseamnă „fișierul nu există”; IsExist, dacă înseamnă „există deja”.os.Truncate: Schimbă dimensiunea unui fișier: taie ce depășește sau completează cu octeți zero.