os.DirFS în Go

Transformă un director de pe disc într-un fs.FS, sistemul de fișiere abstract din Go.

Sintaxă
func DirFS(dir string) fs.FS

Ce face os.DirFS

os.DirFS returnează o valoare fs.FS cu rădăcina în dir. Cu ea poți folosi funcțiile din io/fs (fs.ReadFile, fs.Glob, fs.WalkDir) și le poți da altor pachete care acceptă fs.FS, de exemplu http.FileServerFS sau template.ParseFS.

Căile date unui fs.FS sunt mereu cu /, fără / la început și fără ... Avantaj: același cod merge cu os.DirFS în dezvoltare și cu embed.FS sau un FS de test în producție.

Atenție: DirFS nu este o barieră de securitate completă; legăturile simbolice din director pot arăta în afara lui. Pentru restricție strictă folosește os.Root.

Parametri

Parametru Descriere
dir Directorul care devine rădăcina.

Ce returnează

Un fs.FS. Nu returnează eroare: erorile apar la deschiderea fișierelor.

Exemple

Exemplul 1: Citire prin fs.FS

package main

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

func main() {
    os.MkdirAll("date/orase", 0o755)
    os.WriteFile("date/orase/iasi.txt", []byte("Iași: 271 692 locuitori"), 0o644)

    fsys := os.DirFS("date")
    continut, err := fs.ReadFile(fsys, "orase/iasi.txt")
    fmt.Println(string(continut), err)
}

Rezultat

Iași: 271 692 locuitori <nil>

Exemplul 2: Căutare cu fs.Glob

package main

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

func main() {
    os.Mkdir("poze", 0o755)
    for _, n := range []string{"mare.jpg", "munte.jpg", "lista.txt", "plaja.jpg"} {
        os.WriteFile("poze/"+n, nil, 0o644)
    }
    gasite, _ := fs.Glob(os.DirFS("poze"), "*.jpg")
    fmt.Println(gasite)
}

Rezultat

[mare.jpg munte.jpg plaja.jpg]

Exemplul 3: Căi nevalide

.. și căile care încep cu / sunt refuzate de orice fs.FS.

package main

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

func main() {
    os.Mkdir("public", 0o755)
    fsys := os.DirFS("public")
    _, err := fs.ReadFile(fsys, "../secret.txt")
    fmt.Println(err)
    _, err = fs.ReadFile(fsys, "/etc/passwd")
    fmt.Println(err)
    fmt.Println(fs.ValidPath("css/stil.css"), fs.ValidPath("../x"))
}

Rezultat

readfile ../secret.txt: invalid argument
readfile /etc/passwd: invalid argument
true false

Greșeli frecvente

  • Folosești \ sau filepath.Join pentru căile dintr-un fs.FS. Acolo separatorul este mereu /; folosește path.Join.
  • Crezi că DirFS protejează complet împotriva ieșirii din director. Legăturile simbolice o pot ocoli; folosește os.OpenRoot pentru date nesigure.

Comenzi înrudite

  • os.CopyFS: Copiază tot conținutul unui sistem de fișiere (fs.FS) într-un director de pe disc.
  • embed.FS: Include fișiere și directoare direct în executabil la compilare, ca programul să nu mai depindă de fișiere externe.
  • filepath.WalkDir: Parcurge recursiv un director și apelează o funcție pentru fiecare fișier și subdirector, în ordine alfabetică.
  • filepath.Glob: Returnează toate fișierele de pe disc ale căror nume se potrivesc unui model cu *, ? și [ ].
  • os.OpenRoot: Deschide un director ca rădăcină din care nu se poate ieși; OpenInRoot deschide un fișier strict în interiorul unui director.