[インデックス 16498] ファイルの概要
このコミットは、Go言語の標準ライブラリであるmime
パッケージに、Plan 9オペレーティングシステムにおけるMIMEタイプ(Multipurpose Internet Mail Extensions)のサポートを追加するものです。これにより、GoアプリケーションがPlan 9環境で実行される際に、システムに定義されたMIMEタイプ設定を適切に読み込み、ファイル拡張子からMIMEタイプを判別できるようになります。
コミット
commit 5567592c07b5ef2c9563a511851c7792868f0312
Author: Anthony Martin <ality@pbrane.org>
Date: Tue Jun 4 17:30:45 2013 -0700
mime: add support for Plan 9
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/10028043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5567592c07b5ef2c9563a511851c7792868f0312
元コミット内容
このコミットの目的は、Go言語のmime
パッケージにPlan 9オペレーティングシステム向けのMIMEタイプサポートを追加することです。具体的には、Plan 9のMIMEタイプ定義ファイルを読み込むための新しいコードが導入され、既存のUnix系システム向けのMIMEタイプ処理からPlan 9が除外されています。
変更の背景
Go言語はクロスプラットフォーム対応を重視しており、様々なオペレーティングシステムで動作するように設計されています。MIMEタイプは、インターネット上でファイルの形式を識別するために広く使用される標準です。多くのUnix系システムでは、/etc/mime.types
のようなファイルにMIMEタイプとファイル拡張子のマッピングが定義されています。しかし、Plan 9は独自の設計思想を持つオペレーティングシステムであり、MIMEタイプの定義方法も他のUnix系システムとは異なります。
このコミット以前のGoのmime
パッケージは、主にUnix系システム(Linux, macOS, FreeBSDなど)のMIMEタイプ定義を想定していました。Plan 9環境でGoアプリケーションがMIMEタイプを正確に判別するためには、Plan 9独自のMIMEタイプ定義ファイル(通常/sys/lib/mimetypes
)を読み込むメカニズムが必要でした。この変更は、Goのmime
パッケージがPlan 9環境でも適切に機能し、より広範なOSサポートを提供するためのものです。
前提知識の解説
MIMEタイプ (Multipurpose Internet Mail Extensions)
MIMEタイプは、インターネット上で交換されるファイルやデータの種類を識別するための標準的な方法です。例えば、ウェブサーバーがクライアントにファイルを送信する際、そのファイルがHTMLドキュメントなのか、画像なのか、PDFなのかをMIMEタイプで伝えます。MIMEタイプは通常、「タイプ/サブタイプ」の形式で表現されます(例: text/html
, image/jpeg
, application/pdf
)。Go言語のmime
パッケージは、ファイル拡張子からMIMEタイプを推測したり、MIMEタイプからファイル拡張子を推測したりする機能を提供します。
Plan 9 from Bell Labs
Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソース(ファイル、デバイス、ネットワーク接続など)をファイルシステムとして表現するという特徴を持っています。Plan 9は、そのシンプルで一貫性のある設計、強力なネットワーク機能、そして独自のプロトコルやツールで知られています。MIMEタイプの定義に関しても、他のUnix系システムとは異なる独自のアプローチを採用しています。Plan 9では、MIMEタイプ定義は通常/sys/lib/mimetypes
ファイルに格納されており、そのフォーマットも異なります。
Go言語のビルドタグ (Build Tags)
Go言語には「ビルドタグ」という機能があります。これは、ソースコードファイルの先頭に特定のコメント行(// +build tagname
)を記述することで、そのファイルが特定の環境(OS、アーキテクチャなど)でのみコンパイルされるように制御するメカニズムです。例えば、// +build linux
と書かれたファイルはLinux環境でのみコンパイルされ、他のOSでは無視されます。このコミットでは、type_unix.go
からplan9
ビルドタグを削除し、type_plan9.go
にPlan 9固有のMIMEタイプ処理を分離するために利用されています。
技術的詳細
このコミットの主要な変更点は、Goのmime
パッケージがPlan 9環境でMIMEタイプを処理する方法を分離し、Plan 9固有のMIMEタイプ定義ファイルを読み込むロジックを導入したことです。
-
type_plan9.go
の新規追加:- このファイルは、Plan 9環境でのみコンパイルされるように設計されています(ただし、明示的なビルドタグは付与されていませんが、
type_unix.go
からplan9
が削除されたことで、Plan 9環境ではこのファイルが選択されるようになります)。 typeFiles
というグローバル変数が定義されており、Plan 9のMIMEタイプ定義ファイルである/sys/lib/mimetypes
のパスが格納されています。loadMimeFile
関数は、指定されたMIMEタイプ定義ファイルを読み込み、その内容を解析してGoのmime
パッケージ内部のMIMEタイプマップに登録します。Plan 9のMIMEタイプファイルは、拡張子、タイプ、サブタイプなどがスペース区切りで記述される独自のフォーマットを持っています。この関数は、そのフォーマットを解析し、setExtensionType
関数(mime
パッケージの内部関数)を呼び出してマッピングを登録します。initMime
関数は、typeFiles
に定義されたすべてのMIMEタイプファイルを読み込むためのエントリポイントです。initMimeForTests
関数は、テスト目的でMIMEタイプを初期化するための関数です。これは、実際のシステムファイルではなく、testdata/test.types.plan9
というテスト用のMIMEタイプ定義ファイルを読み込むようにtypeFiles
を上書きします。
- このファイルは、Plan 9環境でのみコンパイルされるように設計されています(ただし、明示的なビルドタグは付与されていませんが、
-
type_unix.go
の変更:- 既存の
type_unix.go
ファイルは、Unix系システム(darwin, freebsd, linux, netbsd, openbsd)向けのMIMEタイプ処理を担っていました。 - このコミットでは、ファイルの先頭にあるビルドタグから
plan9
が削除されました。これにより、Plan 9環境ではtype_unix.go
はコンパイルされなくなり、代わりに新しく追加されたtype_plan9.go
が使用されるようになります。
- 既存の
-
testdata/test.types.plan9
の新規追加:- これは、
type_plan9.go
のloadMimeFile
関数がPlan 9のMIMEタイプ定義ファイルを正しく解析できることを検証するためのテストデータファイルです。 .t1
と.t2
という架空の拡張子に対するMIMEタイプ定義が含まれています。
- これは、
これらの変更により、Goのmime
パッケージは、コンパイルされるオペレーティングシステムに応じて適切なMIMEタイプ定義ファイルを読み込むようになり、Plan 9環境でも正確なMIMEタイプ判別が可能になります。
コアとなるコードの変更箇所
src/pkg/mime/testdata/test.types.plan9
(新規ファイル)
# Copyright 2013 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# mime package test
.t1 application test - y # Simple test
.t2 text test - y # Text test
src/pkg/mime/type_plan9.go
(新規ファイル)
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mime
import (
"bufio"
"os"
"strings"
)
var typeFiles = []string{
"/sys/lib/mimetypes",
}
func loadMimeFile(filename string) {
f, err := os.Open(filename)
if err != nil {
return
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
if len(fields) <= 2 || fields[0][0] != '.' {
continue
}
if fields[1] == "-" || fields[2] == "-" {
continue
}
setExtensionType(fields[0], fields[1]+"/"+fields[2])
}
if err := scanner.Err(); err != nil {
panic(err)
}
}
func initMime() {
for _, filename := range typeFiles {
loadMimeFile(filename)
}
}
func initMimeForTests() map[string]string {
typeFiles = []string{"testdata/test.types.plan9"}
return map[string]string{
".t1": "application/test",
".t2": "text/test; charset=utf-8",
".png": "image/png",
}
}
src/pkg/mime/type_unix.go
(変更箇所)
--- a/src/pkg/mime/type_unix.go
+++ b/src/pkg/mime/type_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd plan9
+// +build darwin freebsd linux netbsd openbsd
package mime
コアとなるコードの解説
src/pkg/mime/type_plan9.go
-
typeFiles
変数:var typeFiles = []string{"/sys/lib/mimetypes"}
: Plan 9システムにおけるMIMEタイプ定義ファイルの標準パスを定義しています。Goのmime
パッケージがMIMEタイプを初期化する際に、このパスのファイルを読み込もうとします。
-
loadMimeFile
関数:- この関数は、指定された
filename
(MIMEタイプ定義ファイル)を開き、行ごとに読み込みます。 bufio.NewScanner
を使用してファイルを効率的にスキャンします。- 各行を
strings.Fields
でスペース区切りに分割し、フィールドの数が2以下の場合や、最初のフィールドがピリオド(.
)で始まらない場合はスキップします。これは、Plan 9のMIMEタイプ定義ファイルのフォーマット(.拡張子 タイプ サブタイプ ...
)に合致しない行を無視するためです。 - タイプまたはサブタイプがハイフン(
-
)の場合もスキップします。これは、MIMEタイプが未定義であることを示す慣習的な表現である可能性があります。 setExtensionType(fields[0], fields[1]+"/"+fields[2])
:解析された拡張子(fields[0]
)と、タイプとサブタイプを結合したMIMEタイプ文字列(例:application/test
)を、mime
パッケージ内部のマップに登録します。setExtensionType
はパッケージ内部の関数であり、外部からは直接呼び出されません。
- この関数は、指定された
-
initMime
関数:for _, filename := range typeFiles { loadMimeFile(filename) }
:typeFiles
に定義されているすべてのMIMEタイプファイルをループで処理し、それぞれloadMimeFile
を呼び出してMIMEタイプをロードします。この関数は、Goのmime
パッケージが初期化される際に、Plan 9環境で自動的に呼び出されることが期待されます。
-
initMimeForTests
関数:typeFiles = []string{"testdata/test.types.plan9"}
: テスト実行時に、実際のシステムファイルではなく、テストデータファイルtestdata/test.types.plan9
を読み込むようにtypeFiles
を上書きします。これにより、テストがシステム環境に依存せず、再現性のあるMIMEタイプ初期化を行うことができます。- この関数は、テストで期待されるMIMEタイプマッピングのサンプルを返します。
src/pkg/mime/type_unix.go
- ビルドタグの変更:
- // +build darwin freebsd linux netbsd openbsd plan9
+ // +build darwin freebsd linux netbsd openbsd
- この変更により、
type_unix.go
はPlan 9環境ではコンパイルされなくなります。これにより、Plan 9固有のMIMEタイプ処理がtype_plan9.go
に完全に分離され、各OSのMIMEタイプ処理が適切にモジュール化されます。
これらの変更により、Goのmime
パッケージは、Plan 9環境においてもそのMIMEタイプ定義を適切に読み込み、ファイル拡張子からMIMEタイプを正確に判別できるようになりました。
関連リンク
- Go言語
mime
パッケージのドキュメント: https://pkg.go.dev/mime - Plan 9 from Bell Labs 公式サイト: https://9p.io/plan9/
- MIME (Multipurpose Internet Mail Extensions) - Wikipedia: https://ja.wikipedia.org/wiki/MIME
参考にした情報源リンク
- Go言語のソースコード (特に
src/mime
ディレクトリ) - Plan 9のMIMEタイプ定義に関する一般的な情報 (Web検索)
- Go言語のビルドタグに関するドキュメント (Web検索)
- コミットメッセージに記載されているGoのコードレビューリンク: https://golang.org/cl/10028043