Maison >développement back-end >Golang >Comment obtenir une copie de fichiers robuste et efficace dans Go Beyond os.Link() ?

Comment obtenir une copie de fichiers robuste et efficace dans Go Beyond os.Link() ?

Barbara Streisand
Barbara Streisandoriginal
2024-11-27 03:49:091008parcourir

How to Achieve Robust and Efficient File Copy in Go Beyond os.Link()?

Copie de fichiers dans Go : au-delà des bases

La simplicité de la copie de fichiers dans Go peut être trompeuse. Bien que la fonction os.Link() fournisse une méthode prétendument efficace, ses limites nécessitent une approche plus complète.

Les bizarreries de Link()

Os.Link() crée un lien physique entre deux fichiers, évitant la surcharge de transfert d'octets. Cependant, cette approche comporte des restrictions inhérentes. Différents systèmes d'exploitation imposent des contraintes variables sur les liens physiques. Dans certains scénarios, les appels Link() peuvent échouer.

Copie de fichier robuste

Pour une copie robuste et efficace, les étapes suivantes sont recommandées :

  1. Vérifications préalables à la copie : Vérifiez si la copie est réalisable (par exemple, autorisations, répertoires existent).
  2. Vérification du même fichier : Déterminez si les deux fichiers existent et sont identiques à l'aide de os.SameFile.
  3. Tentative de lien : Essayez d'établir un lien physique via os.Link.
  4. Byte-Copy Fallback : En cas de liaison échoue, copiez octet par octet à l'aide de io.Copy.

Dans certains cas, vous préférerez peut-être des fonctions distinctes pour la copie synchrone (bloquante) et asynchrone (non bloquante).

Exemple optimisé

L'extrait de code suivant implémente une fonction complète de copie de fichiers, CopyFile(), qui intègre les étapes recommandées :

package main

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

// CopyFile implements a robust and efficient file copy.
func CopyFile(src, dst string) (err error) {
    sfi, err := os.Stat(src)
    if err != nil {
        return err
    }
    if !sfi.Mode().IsRegular() {
        return fmt.Errorf("CopyFile: Non-regular source file %s (%q)", sfi.Name(), sfi.Mode())
    }
    dfi, err := os.Stat(dst)
    if err != nil {
        if os.IsNotExist(err) {
            return nil // Destination file doesn't exist, so no copying required.
        }
        return err
    }
    if !(dfi.Mode().IsRegular()) {
        return fmt.Errorf("CopyFile: Non-regular destination file %s (%q)", dfi.Name(), dfi.Mode())
    }
    if os.SameFile(sfi, dfi) {
        return nil // Files are identical, so no copying required.
    }
    if err = os.Link(src, dst); err == nil {
        return nil // Hard link succeeded.
    }
    err = copyFileContents(src, dst)
    return err
}

// copyFileContents performs a byte-wise copy of the source file to the destination file.
func copyFileContents(src, dst string) error {
    in, err := os.Open(src)
    if err != nil {
        return err
    }
    defer in.Close()
    out, err := os.Create(dst)
    if err != nil {
        return err
    }
    defer func() {
        if err == nil {
            err = out.Close()
        }
    }()
    if _, err = io.Copy(out, in); err != nil {
        return err
    }
    return out.Sync()
}

Cette fonction allie efficacité, robustesse et manipulation pour divers cas extrêmes.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn