ホームページ  >  記事  >  バックエンド開発  >  Go Beyond os.Link() で堅牢かつ効率的なファイル コピーを実現するにはどうすればよいですか?

Go Beyond os.Link() で堅牢かつ効率的なファイル コピーを実現するにはどうすればよいですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-11-27 03:49:09941ブラウズ

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

Go でのファイル コピー: 基本を超えて

Go でのファイル コピーの単純さは誤解を招く可能性があります。 os.Link() 関数は効率的であると称されるメソッドを提供しますが、その制限により、より包括的なアプローチが必要になります。

Link() Quirks

Os.Link() 2 つのファイル間のハード リンクにより、バイト転送のオーバーヘッドが回避されます。ただし、このアプローチには固有の制限があります。オペレーティング システムが異なると、ハード リンクにさまざまな制約が課されます。特定のシナリオでは、Link() 呼び出しが失敗することがあります。

堅牢なファイル コピー

堅牢で効率的なコピーを行うには、次の手順をお勧めします。

  1. コピー前チェック: コピーが可能かどうかを確認します (例:
  2. 同じファイル チェック: os.SameFile を使用して両方のファイルが存在し、同一であるかどうかを確認します。
  3. リンク試行:経由でハードリンクを確立してみてくださいos.Link.
  4. Byte-Copy Fallback: リンクが失敗した場合は、io.Copy を使用してバイト単位でコピーします。

場合によっては、同期 (ブロッキング) と非同期 (ノンブロッキング) の別々の関数

最適化された例

次のコード スニペットは、推奨される手順を組み込んだ包括的なファイル コピー関数 CopyFile() を実装します。

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()
}

この機能は、効率性、堅牢性、さまざまなエッジケースへの対応を組み合わせています。

以上がGo Beyond os.Link() で堅牢かつ効率的なファイル コピーを実現するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。