os.Open în Go

Deschide un fișier existent doar pentru citire și returnează un *os.File.

Sintaxă
func Open(name string) (*File, error)

Ce face os.Open

os.Open este modul obișnuit de a deschide un fișier ca să citești din el. Fișierul trebuie să existe; este deschis doar pentru citire (echivalent cu os.OpenFile(nume, os.O_RDONLY, 0)), iar orice încercare de scriere dă eroare.

Rezultatul este un *os.File, care implementează io.Reader. Îl dai mai departe lui bufio.NewScanner (citire rând cu rând), io.Copy, json.NewDecoder, csv.NewReader etc. Imediat după verificarea erorii scrii defer f.Close().

Poți deschide cu os.Open și un director, ca să-i citești conținutul cu f.ReadDir. Pentru a citi tot fișierul dintr-un singur apel, os.ReadFile este mai simplu.

Parametri

Parametru Descriere
name Calea fișierului, relativă la directorul curent sau absolută.

Ce returnează

Fișierul deschis și nil, sau nil și o eroare *fs.PathError (fișier inexistent, lipsă drepturi).

Exemple

Exemplul 1: Citire rând cu rând

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    os.WriteFile("orase.txt", []byte("Iași\nCluj-Napoca\nTimișoara\n"), 0o644)

    f, err := os.Open("orase.txt")
    if err != nil {
        fmt.Println("eroare:", err)
        return
    }
    defer f.Close()

    s := bufio.NewScanner(f)
    for s.Scan() {
        fmt.Println("oraș:", s.Text())
    }
    if err := s.Err(); err != nil {
        fmt.Println("eroare la citire:", err)
    }
}

Rezultat

oraș: Iași
oraș: Cluj-Napoca
oraș: Timișoara

Exemplul 2: Fișier inexistent și scriere refuzată

package main

import (
    "errors"
    "fmt"
    "io/fs"
    "os"
)

func main() {
    _, err := os.Open("comenzi-2024.csv")
    fmt.Println("eroare:", err)
    fmt.Println("nu există:", errors.Is(err, fs.ErrNotExist))

    os.WriteFile("note.txt", []byte("Ana 9\n"), 0o644)
    f, _ := os.Open("note.txt")
    defer f.Close()
    _, err = f.WriteString("Mihai 7\n")
    fmt.Println("scriere:", err)
}

Rezultat

eroare: open comenzi-2024.csv: no such file or directory
nu există: true
scriere: write note.txt: bad file descriptor

Exemplul 3: JSON citit direct din fișier

json.NewDecoder primește fișierul ca io.Reader, fără să-l citim întâi în memorie.

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Setari struct {
    Port int    `json:"port"`
    Oras string `json:"oras"`
}

func main() {
    os.WriteFile("setari.json", []byte(`{"port": 8080, "oras": "Brașov"}`), 0o644)

    f, err := os.Open("setari.json")
    if err != nil {
        fmt.Println("eroare:", err)
        return
    }
    defer f.Close()

    var s Setari
    if err := json.NewDecoder(f).Decode(&s); err != nil {
        fmt.Println("JSON greșit:", err)
        return
    }
    fmt.Printf("%+v\n", s)
}

Rezultat

{Port:8080 Oras:Brașov}

Greșeli frecvente

  • Scrii defer f.Close() înainte de if err != nil. Dacă deschiderea a eșuat, f este nil.
  • Încerci să scrii într-un fișier deschis cu os.Open. Pentru scriere folosește os.Create sau os.OpenFile.
  • Deschizi multe fișiere într-o buclă cu defer f.Close() direct în buclă. Fișierele se închid abia la ieșirea din funcție; mută corpul buclei într-o funcție separată.

Comenzi înrudite

  • os.Create: Creează un fișier nou (sau golește unul existent) și îl deschide pentru scriere și citire.
  • os.OpenFile: Deschide un fișier cu opțiuni alese de tine: citire, scriere, adăugare la final, creare, golire, creare exclusivă.
  • os.File: Tipul care reprezintă un fișier deschis; îl obții cu os.Open, os.Create sau os.OpenFile.
  • os.ReadFile: Citește tot conținutul unui fișier într-un slice de octeți, dintr-un singur apel.
  • bufio.NewScanner: Creează un bufio.Scanner, cel mai simplu mod de a citi un text rând cu rând (sau cuvânt cu cuvânt).
  • os.File.Close: Închide fișierul și eliberează resursele sistemului; după Close fișierul nu mai poate fi folosit.