Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 17345] ファイルの概要

このコミットは、Go 1.2 リリースノートのドキュメントファイル doc/go1.2.txt に対する変更です。具体的には、archive/tar および archive/zip パッケージにおける os.FileInfo の実装に関する破壊的変更について追記しています。

コミット

commit 478c871f02f3b1b9b5c768a5d19fe7450b760dfd
Author: Rob Pike <r@golang.org>
Date:   Wed Aug 21 08:37:32 2013 +1000

    doc/go1.2.txt: archive/tar's fixed FileInfo
    
    R=golang-dev, dsymonds
    CC=golang-dev
    https://golang.org/cl/13140043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/478c871f02f3b1b9b5c768a5d19fe7450b760dfd

元コミット内容

 doc/go1.2.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/doc/go1.2.txt b/doc/go1.2.txt
index e23a579d5c..85dd2e2c56 100644
--- a/doc/go1.2.txt
+++ b/doc/go1.2.txt
@@ -14,6 +14,9 @@ crypto/des: 5x faster encoding/decoding (CL 11874043, 12072045).
 encoding/json: faster encoding (CL 9129044).
 net: improve windows performance by up to 30% (CL 8670044).
 
+Breaking change:
+archive/tar,archive/zip: fix os.FileInfo implementation to provide base name only (CL 13118043).
+\n cmd/5a: removed support for R9/R10 (use m/g instead) (CL 9840043).
 cmd/5l: add MOVBS, MOVHS etc for sub-word moves (CL 12682043).
 cmd/cgo, cmd/go: support including C++ code with cgo (CL 8248043).

変更の背景

このコミットは、Go 1.2 のリリースノートに、archive/tar および archive/zip パッケージにおける重要な破壊的変更を明記するために行われました。この変更は、os.FileInfo インターフェースの実装が、ファイル名として完全なパスではなく、ベース名(ファイル名のみでディレクトリ情報は含まない)のみを返すように修正されたことによるものです。

Go の標準ライブラリでは、os.FileInfo インターフェースはファイルに関するメタデータ(名前、サイズ、パーミッション、更新時刻など)を提供します。Name() メソッドは、通常、ファイルまたはディレクトリのベース名を返すと期待されます。しかし、以前の archive/tar および archive/zip パッケージの実装では、os.FileInfo.Name() がアーカイブ内のエントリの完全なパスを返してしまうという問題がありました。これは、os.FileInfo の一般的なセマンティクスと矛盾し、このインターフェースを利用する他の Go コードとの互換性の問題を引き起こす可能性がありました。

この不整合を修正し、os.FileInfo の期待される動作に合わせるために、archive/tar および archive/zip パッケージの os.FileInfo 実装が変更されました。この修正は、既存のコードが os.FileInfo.Name() の戻り値に完全なパスを期待している場合に、予期せぬ動作やバグを引き起こす可能性があるため、「破壊的変更 (Breaking change)」としてリリースノートに記載する必要がありました。

前提知識の解説

Go 言語

Go(Golang)は、Googleによって開発されたオープンソースのプログラミング言語です。静的型付け、コンパイル型言語であり、並行処理、ガベージコレクション、メモリ安全性に重点を置いています。システムプログラミング、Webサービス、ネットワークプログラミングなどで広く利用されています。

os.FileInfo インターフェース

Go の標準ライブラリ os パッケージには、ファイルシステム上のファイルやディレクトリに関する情報を提供する FileInfo インターフェースが定義されています。このインターフェースは以下のメソッドを持ちます。

type FileInfo interface {
    Name() string       // base name of the file
    Size() int64        // length in bytes for regular files; system-dependent for others
    Mode() FileMode     // file mode bits
    ModTime() time.Time // modification time
    IsDir() bool        // abbreviation for Mode().IsDir()
    Sys() interface{}   // underlying data source (can return nil)
}

特に重要なのは Name() メソッドで、これは「ファイルのベース名」を返すことが期待されています。ベース名とは、パスの最後の要素、つまりファイル名自体であり、ディレクトリパスは含まれません。例えば、/path/to/file.txt のベース名は file.txt です。

archive/tar および archive/zip パッケージ

  • archive/tar: TARアーカイブ(テープアーカイブ)の読み書きを実装したパッケージです。TARファイルは、複数のファイルを一つのアーカイブにまとめるための一般的な形式です。
  • archive/zip: ZIPアーカイブの読み書きを実装したパッケージです。ZIPファイルもまた、ファイルを圧縮してアーカイブするための広く使われている形式です。

これらのパッケージは、アーカイブ内の各エントリ(ファイルやディレクトリ)を表現するために os.FileInfo インターフェースを利用していました。

破壊的変更 (Breaking Change)

ソフトウェア開発において、破壊的変更とは、新しいバージョンのソフトウェアが古いバージョンと互換性がなく、古いバージョンで動作していたコードが新しいバージョンでは動作しなくなるような変更を指します。APIのシグネチャ変更、セマンティクスの変更、機能の削除などがこれに該当します。Go のような安定性を重視する言語では、破壊的変更は慎重に行われ、通常はリリースノートで明確に文書化されます。

技術的詳細

このコミットが参照している CL 13118043 は、archive/tar および archive/zip パッケージにおける os.FileInfo.Name() メソッドの動作を修正するものです。

以前の実装では、archive/tartar.Header 構造体や archive/zipzip.File 構造体が os.FileInfo インターフェースを実装する際に、Name() メソッドがアーカイブ内のエントリの完全なパス(例: dir/subdir/file.txt)を返していました。これは、os.FileInfo のドキュメントに記載されている「ベース名」を返すというセマンティクスに反していました。

この修正により、tar.Header および zip.FileName() メソッドは、filepath.Base() 関数を使用して、エントリのパスからベース名のみを抽出して返すようになりました。

例えば、アーカイブ内に foo/bar/baz.txt というエントリがあった場合:

  • 修正前: os.FileInfo.Name()foo/bar/baz.txt を返していた。
  • 修正後: os.FileInfo.Name()baz.txt を返すようになった。

この変更は、os.FileInfo インターフェースの契約を遵守し、Go エコシステム全体での一貫性を保つために不可欠でした。しかし、もし開発者が archive/tararchive/zip から取得した os.FileInfoName() メソッドが完全なパスを返すことに依存していた場合、この変更によってそのコードは正しく動作しなくなります。そのため、Go 1.2 のリリースノートに「Breaking change」として明記する必要がありました。

コアとなるコードの変更箇所

このコミット自体は、doc/go1.2.txt というドキュメントファイルに3行を追加するものです。

--- a/doc/go1.2.txt
+++ b/doc/go1.2.txt
@@ -14,6 +14,9 @@ crypto/des: 5x faster encoding/decoding (CL 11874043, 12072045).
 encoding/json: faster encoding (CL 9129044).
 net: improve windows performance by up to 30% (CL 8670044).
 
+Breaking change:
+archive/tar,archive/zip: fix os.FileInfo implementation to provide base name only (CL 13118043).
+\n cmd/5a: removed support for R9/R10 (use m/g instead) (CL 9840043).
 cmd/5l: add MOVBS, MOVHS etc for sub-word moves (CL 12682043).
 cmd/cgo, cmd/go: support including C++ code with cgo (CL 8248043).

追加された行は以下の通りです。

Breaking change:
archive/tar,archive/zip: fix os.FileInfo implementation to provide base name only (CL 13118043).

この変更は、Go 1.2 のリリースノートに、archive/tararchive/zip パッケージの os.FileInfo 実装に関する破壊的変更を明確に記載するためのものです。

コアとなるコードの解説

このコミット自体は Go のソースコードの動作を変更するものではなく、Go 1.2 のリリースノート (doc/go1.2.txt) に情報を追加するものです。したがって、直接的な「コアとなるコードの解説」は、このコミットの範囲内にはありません。

しかし、このコミットが言及している CL 13118043 で行われた実際のコード変更は、archive/tararchive/zip パッケージの内部実装にあります。具体的には、tar.Headerzip.Fileos.FileInfo インターフェースを実装する際の Name() メソッドのロジックが変更されました。

例えば、archive/tar パッケージでは、Header 構造体が os.FileInfo を実装しており、その Name() メソッドは以下のように変更されました(概念的な説明であり、実際のコードはより複雑な場合があります):

変更前 (概念):

func (h *Header) Name() string {
    return h.Name // h.Name が完全なパスを保持していた
}

変更後 (概念):

import "path/filepath"

func (h *Header) Name() string {
    return filepath.Base(h.Name) // h.Name からベース名のみを抽出
}

同様の変更が archive/zip パッケージの zip.File 構造体にも適用されました。この修正により、os.FileInfoName() メソッドが常にベース名を返すという Go の慣習と期待に沿うようになりました。

関連リンク

参考にした情報源リンク