os.NewFile în Go

Creează un *os.File dintr-un descriptor de fișier numeric deja deschis (de exemplu 3, moștenit de la părinte).

Sintaxă
func NewFile(fd uintptr, name string) *File

Ce face os.NewFile

Sistemul de operare identifică fiecare fișier deschis printr-un număr, descriptorul de fișier: 0 este intrarea standard, 1 ieșirea standard, 2 ieșirea de erori. os.NewFile învelește un asemenea număr într-un *os.File, ca să-l poți folosi cu toate funcțiile obișnuite. name este doar o etichetă, returnată de f.Name().

Este o funcție de nivel scăzut. Apare când un proces părinte îți dă fișiere deschise (cmd.ExtraFiles din os/exec le transmite copilului ca descriptorii 3, 4, …), la activarea prin socket a systemd sau când lucrezi direct cu syscall. Dacă fd nu este valid, rezultatul este nil. Numărul unui fișier existent îl afli cu f.Fd().

Parametri

Parametru Descriere
fd Descriptorul de fișier.
name Numele afișat pentru fișier.

Ce returnează

Un *os.File, sau nil dacă descriptorul nu este valid.

Exemple

Exemplul 1: Ieșirea standard sub alt nume

package main

import (
    "fmt"
    "os"
)

func main() {
    iesire := os.NewFile(1, "ecran") // descriptorul 1 = ieșirea standard
    fmt.Fprintln(iesire, "scris prin descriptorul 1")
    fmt.Println("nume:", iesire.Name())
    fmt.Println("os.Stdout are descriptorul", os.Stdout.Fd())
}

Rezultat

scris prin descriptorul 1
nume: ecran
os.Stdout are descriptorul 1

Exemplul 2: Fișier transmis unui proces copil

Părintele deschide un fișier și îl dă copilului prin ExtraFiles; în copil, fișierul are descriptorul 3. Programul se pornește pe el însuși cu argumentul copil.

package main

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

func main() {
    if len(os.Args) > 1 && os.Args[1] == "copil" {
        f := os.NewFile(3, "comenzi-de-la-parinte")
        date, _ := io.ReadAll(f)
        fmt.Printf("copilul a citit din %s: %q\n", f.Name(), date)
        return
    }

    os.WriteFile("comenzi.txt", []byte("1042,1043"), 0o644)
    f, _ := os.Open("comenzi.txt")
    defer f.Close()

    exe, _ := os.Executable()
    cmd := exec.Command(exe, "copil")
    cmd.ExtraFiles = []*os.File{f}
    iesire, err := cmd.Output()
    fmt.Print(string(iesire))
    fmt.Println("eroare:", err)
}

Rezultat

copilul a citit din comenzi-de-la-parinte: "1042,1043"
eroare: <nil>

Greșeli frecvente

  • Creezi două *os.File pentru același descriptor și le închizi pe amândouă. Al doilea Close poate închide un alt fișier care a primit între timp același număr.

Comenzi înrudite

  • os.File: Tipul care reprezintă un fișier deschis; îl obții cu os.Open, os.Create sau os.OpenFile.
  • os.Pipe: Creează un pipe al sistemului de operare: ce scrii la un capăt (w) poți citi la celălalt (r).
  • exec.Cmd: Structura care descrie o comandă externă: programul, argumentele, directorul, mediul și intrarea/ieșirile ei.
  • os.Open: Deschide un fișier existent doar pentru citire și returnează un *os.File.