[インデックス 1754] ファイルの概要
このコミットは、Go言語の標準ライブラリからcontainer/array
パッケージを削除するものです。これは、Go言語が初期段階にあった頃の設計判断と、その後の言語進化における重要なマイルストーンを示しています。特に、Goの組み込みスライス型が、より柔軟で効率的な動的配列の代替として確立されていく過程の一部を垣間見ることができます。
コミット
commit 5b814d02f2e4ea8336e1555474724c84e9022de1
Author: Rob Pike <r@golang.org>
Date: Thu Mar 5 13:31:03 2009 -0800
delete deprecated files.
deletion beats documentation for deprecation.
R=rsc,gri
DELTA=509 (2 added, 490 deleted, 17 changed)
OCL=25737
CL=25768
---
src/lib/Makefile | 8 +-
src/lib/container/array/Makefile | 63 ------------
src/lib/container/array/array.go | 186 ----------------------------------
src/lib/container/array/array_test.go | 172 -------------------------------\n src/lib/container/array/intarray.go | 68 -------------\n src/lib/json/generic.go | 8 +-\n src/lib/json/parse.go | 1 -\n src/lib/regexp/regexp.go | 12 +--
8 files changed, 12 insertions(+), 506 deletions(-)
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5b814d02f2e4ea8336e1555474724c84e9022de1
元コミット内容
delete deprecated files.
deletion beats documentation for deprecation.
変更の背景
このコミットの背景には、Go言語の初期開発におけるデータ構造の設計思想の進化があります。Go言語は、C言語のような静的型付け言語の効率性と、PythonやJavaScriptのような動的型付け言語の柔軟性を両立させることを目指していました。その中で、可変長配列のような動的なコレクションをどのように扱うかは重要な課題でした。
初期のGo言語には、container/array
パッケージが存在し、これはジェネリックな配列(Element interface{}
を要素とする)と、特定の型(int
)に特化した配列(IntArray
)を提供していました。しかし、Go言語の設計者たちは、より強力で言語に組み込まれた動的配列の概念が必要であると認識していました。
このコミットは、container/array
パッケージが非推奨となり、その機能がより優れた代替手段、具体的にはcontainer/vector
パッケージ(そして最終的にはGoの組み込みスライス)に置き換えられる過程の一部です。コミットメッセージにある「deletion beats documentation for deprecation.(非推奨のドキュメント化よりも削除が勝る)」という言葉は、Go開発チームが非推奨となったコードを積極的に削除し、クリーンで進化し続ける標準ライブラリを維持しようとする姿勢を明確に示しています。これは、古いコードベースが残り続けることによる混乱やメンテナンスコストを避けるための重要な原則です。
前提知識の解説
このコミットを理解するためには、以下のGo言語の基本的な概念と、当時のGo言語の標準ライブラリの状況について知っておく必要があります。
- Go言語のパッケージシステム: Go言語のコードはパッケージにまとめられ、他のパッケージからインポートして利用します。
src/lib/container/array
は、container
という親パッケージの下にあるarray
というサブパッケージを指します。 - Makefile: Go言語の初期には、C言語プロジェクトのように
Makefile
がビルドプロセスを管理するために広く使われていました。このコミットでは、削除されるパッケージに関連するMakefile
のエントリも削除されています。 - ジェネリクス(Generics)の不在(当時): このコミットが行われた2009年当時、Go言語にはまだジェネリクス(型パラメータ)がありませんでした。そのため、異なる型の要素を扱う動的なコレクションを実装するには、
interface{}
型(Goにおける任意の型を表す)を使用するか、特定の型に特化した実装(例:IntArray
)を作成する必要がありました。container/array
パッケージは、この制約の中でジェネリックな配列機能を提供しようとしていました。 container/vector
パッケージ:container/array
が削除された後、その代替としてcontainer/vector
パッケージが使用されるようになりました。container/vector
もまた、interface{}
を要素とする動的なコレクションを提供しましたが、最終的にはこれもGoの組み込みスライス型に置き換えられ、標準ライブラリから削除されました。- Goの組み込みスライス (Slices): 現在のGo言語において、動的な配列を扱うための主要なメカニズムは「スライス」です。スライスは、基になる配列への参照、長さ、容量を持つ軽量なデータ構造です。
append
関数などを使って動的にサイズを変更でき、Goのコレクション操作の大部分を担っています。このコミットは、Goがcontainer/array
からcontainer/vector
へ、そして最終的に組み込みスライスへと進化していく過渡期を示しています。
技術的詳細
このコミットの技術的な核心は、container/array
パッケージの完全な削除と、それに伴う依存関係の更新です。
container/array
パッケージは、array.go
、array_test.go
、intarray.go
の3つの主要なファイルで構成されていました。
array.go
:Array
型を定義し、Element interface{}
を要素とする動的な配列機能を提供していました。Init
,New
,Len
,At
,Set
,Last
,Insert
,Delete
,InsertArray
,Cut
,Slice
,Do
,Push
,Pop
,AppendArray
といったメソッドが含まれていました。また、LessInterface
を実装することでソート機能もサポートしていました。array_test.go
:array.go
で定義されたArray
型のテストコードが含まれていました。intarray.go
:IntArray
型を定義し、array.Array
を埋め込むことで、int
型に特化した配列機能を提供していました。これは、ジェネリクスがないGoの初期において、型安全なコレクションを提供するための一般的なパターンでした。
このコミットでは、これらのファイルがすべて削除されています。
また、src/lib/Makefile
が更新され、container/array
に関連するビルドターゲットや依存関係が削除されています。これは、ビルドシステムから非推奨パッケージへの参照を完全に排除するためです。
さらに重要なのは、container/array
に依存していた他の標準ライブラリパッケージの更新です。
src/lib/json/generic.go
: このファイルでは、JSONのパースと生成に関連する_Array
型が、*array.Array
から*vector.Vector
に、そして_JsonBuilder
内のa *array.Array
もa *vector.Vector
に変更されています。これは、JSON処理において動的な配列を扱う際に、container/array
の代わりにcontainer/vector
を使用するように切り替えたことを意味します。src/lib/json/parse.go
:json
パッケージのパース関連のファイルからも"array"
のインポートが削除されています。src/lib/regexp/regexp.go
: 正規表現エンジン内で使用されるRegexp
構造体のinst
フィールドが*array.Array
から*vector.Vector
に、_CharClass
構造体のranges
フィールドが*array.IntArray
から*vector.IntVector
に変更されています。また、newCharClass
関数やcompiler
関数内のarray.New
やarray.NewIntArray
の呼び出しも、それぞれvector.New
やvector.NewIntVector
に置き換えられています。これは、正規表現の内部処理で動的なデータ構造を扱う際に、container/array
の代わりにcontainer/vector
を使用するように切り替えたことを意味します。
これらの変更は、container/array
がGo言語の標準ライブラリから完全に排除され、その役割がcontainer/vector
に引き継がれたことを明確に示しています。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、以下のファイルの削除と、container/array
への参照をcontainer/vector
に置き換えることです。
-
src/lib/container/array/Makefile
の削除:--- a/src/lib/container/array/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2009 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. - -# DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m >Makefile -O=6 -GC=$(O)g -CC=$(O)c -w -AS=$(O)a -AR=$(O)ar - -default: packages - -clean: - rm -f *.$O *.a $O.out - -test: packages - gotest - -coverage: packages - gotest - 6cov -g `pwd` | grep -v '_test\\.go:' - -%.$O: %.go - $(GC) $*.go - -%.$O: %.c - $(CC) $*.c - -%.$O: %.s - $(AS) $*.s - -O1=\\ - array.$O\\ - -O2=\\ - intarray.$O\\ - -array.a: a1 a2 - -a1: $(O1) - $(AR) grc array.a array.$O - rm -f $(O1) - -a2: $(O2) - $(AR) grc array.a intarray.$O - rm -f $(O2) - -newpkg: clean - $(AR) grc array.a - -$(O1): newpkg -$(O2): a1 - -nuke: clean - rm -f $(GOROOT)/pkg/array.a - -packages: array.a - -install: packages - cp array.a $(GOROOT)/pkg/array.a
-
src/lib/container/array/array.go
の削除: (ファイル全体が削除されているため、差分は省略) -
src/lib/container/array/array_test.go
の削除: (ファイル全体が削除されているため、差分は省略) -
src/lib/container/array/intarray.go
の削除: (ファイル全体が削除されているため、差分は省略) -
src/lib/json/generic.go
の変更:array
パッケージのインポートが削除され、vector
パッケージがインポートされています。_Array
構造体と_JsonBuilder
構造体内のarray.Array
型がvector.Vector
型に置き換えられています。_JsonBuilder
のArray()
メソッド内でarray.New(0)
がvector.New(0)
に変更されています。--- a/src/lib/json/generic.go +++ b/src/lib/json/generic.go @@ -7,12 +7,12 @@ package json import ( - "array"; "fmt"; "math"; "json"; "strconv"; "strings"; + "vector"; ) const ( @@ -68,7 +68,7 @@ func (j *_Number) String() string { return fmt.Sprintf("%g", j.f); } -type _Array struct { a *array.Array; _Null } +type _Array struct { a *vector.Vector; _Null } func (j *_Array) Kind() int { return ArrayKind } func (j *_Array) Len() int { return j.a.Len() } func (j *_Array) Elem(i int) Json { @@ -208,7 +208,7 @@ type _JsonBuilder struct { ptr *Json; // or to a[i] (can't set ptr = &a[i]) - a *array.Array; + a *vector.Vector; i int; // or to m[k] (can't set ptr = &m[k]) @@ -265,7 +265,7 @@ func (b *_JsonBuilder) String(s string) { func (b *_JsonBuilder) Array() { - b.Put(&_Array{array.New(0), _Null{}}) + b.Put(&_Array{vector.New(0), _Null{}}) } func (b *_JsonBuilder) Map() {
-
src/lib/regexp/regexp.go
の変更:array
パッケージのインポートが削除され、vector
パッケージがインポートされています。Regexp
構造体内のinst
フィールドが*array.Array
から*vector.Vector
に置き換えられています。_CharClass
構造体内のranges
フィールドが*array.IntArray
から*vector.IntVector
に置き換えられています。newCharClass
関数内でarray.NewIntArray(0)
がvector.NewIntVector(0)
に変更されています。compiler
関数内でarray.New(0)
がvector.New(0)
に変更されています。--- a/src/lib/regexp/regexp.go +++ b/src/lib/regexp/regexp.go @@ -23,9 +23,9 @@ package regexp import ( - "array"; "os"; "utf8"; + "vector"; ) var debug = false; @@ -69,7 +69,7 @@ type Regexp struct { expr string; // the original expression ch chan<- *Regexp; // reply channel when we're done error *os.Error; // compile- or run-time error; nil if OK - inst *array.Array; + inst *vector.Vector; start instr; nbra int; // number of brackets in expression, for subexpressions } @@ -142,8 +142,8 @@ type _CharClass struct { common; char int; negate bool; // is character class negated? ([^a-z]) - // array of int, stored pairwise: [a-z] is (a,z); x is (x,x): - ranges *array.IntArray; + // vector of int, stored pairwise: [a-z] is (a,z); x is (x,x): + ranges *vector.IntVector; } func (cclass *_CharClass) kind() int { return _CHARCLASS } @@ -183,7 +183,7 @@ func (cclass *_CharClass) matches(c int) bool { func newCharClass() *_CharClass { c := new(_CharClass); - c.ranges = array.NewIntArray(0); + c.ranges = vector.NewIntVector(0); return c; } @@ -576,7 +576,7 @@ func (re *Regexp) doParse() { func compiler(str string, ch chan *Regexp) { re := new(Regexp); re.expr = str; - re.inst = array.New(0); + re.inst = vector.New(0); re.ch = ch; re.doParse(); ch <- re;
コアとなるコードの解説
このコミットの主要な目的は、Go言語の標準ライブラリからcontainer/array
パッケージを完全に削除することです。これは、Go言語がより洗練されたデータ構造の設計へと移行する過程の一部であり、特に組み込みスライス型の導入に向けた重要なステップでした。
container/array
パッケージは、Goの初期段階でジェネリクスがない中で動的な配列機能を提供するために存在していました。しかし、その実装はinterface{}
型に依存しており、型安全性の面で課題がありました。また、パフォーマンスも最適とは言えませんでした。
このコミットでは、container/array
パッケージのソースコードファイル(array.go
, array_test.go
, intarray.go
)と、そのビルド設定ファイル(Makefile
)が完全に削除されています。これにより、Goの標準ライブラリからこの非推奨パッケージが物理的に排除されます。
さらに、json
パッケージとregexp
パッケージという、Goの他の重要な標準ライブラリがcontainer/array
に依存していたため、これらのパッケージも更新されています。具体的には、container/array
への参照がすべてcontainer/vector
に置き換えられています。これは、container/vector
がcontainer/array
の直接的な後継として位置づけられていたことを示しています。container/vector
もまた、interface{}
を要素とする動的なコレクションを提供しましたが、その後のGo言語の進化により、最終的には組み込みスライス型がこれらのパッケージの役割を担うことになります。
この変更は、Go言語の設計哲学である「シンプルさ」と「効率性」を追求する姿勢を反映しています。非推奨となったコードを積極的に削除することで、ライブラリの複雑性を減らし、開発者がより推奨されるイディオムやデータ構造に集中できるように促しています。
関連リンク
- Go言語の公式ドキュメント(現在のスライスに関する情報): https://go.dev/blog/slices-intro
- Go言語の
container
パッケージ(現在の内容): https://pkg.go.dev/container
参考にした情報源リンク
- Go言語の配列とスライスに関するStack Overflowの議論:
- Go言語の
container/vector
パッケージの非推奨化に関する情報: - Go言語の配列とスライスの違いに関する記事:
- Go言語の
container
パッケージの現在の内容に関する記事: