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

[インデックス 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言語の標準ライブラリの状況について知っておく必要があります。

  1. Go言語のパッケージシステム: Go言語のコードはパッケージにまとめられ、他のパッケージからインポートして利用します。src/lib/container/arrayは、containerという親パッケージの下にあるarrayというサブパッケージを指します。
  2. Makefile: Go言語の初期には、C言語プロジェクトのようにMakefileがビルドプロセスを管理するために広く使われていました。このコミットでは、削除されるパッケージに関連するMakefileのエントリも削除されています。
  3. ジェネリクス(Generics)の不在(当時): このコミットが行われた2009年当時、Go言語にはまだジェネリクス(型パラメータ)がありませんでした。そのため、異なる型の要素を扱う動的なコレクションを実装するには、interface{}型(Goにおける任意の型を表す)を使用するか、特定の型に特化した実装(例: IntArray)を作成する必要がありました。container/arrayパッケージは、この制約の中でジェネリックな配列機能を提供しようとしていました。
  4. container/vectorパッケージ: container/arrayが削除された後、その代替としてcontainer/vectorパッケージが使用されるようになりました。container/vectorもまた、interface{}を要素とする動的なコレクションを提供しましたが、最終的にはこれもGoの組み込みスライス型に置き換えられ、標準ライブラリから削除されました。
  5. Goの組み込みスライス (Slices): 現在のGo言語において、動的な配列を扱うための主要なメカニズムは「スライス」です。スライスは、基になる配列への参照、長さ、容量を持つ軽量なデータ構造です。append関数などを使って動的にサイズを変更でき、Goのコレクション操作の大部分を担っています。このコミットは、Goがcontainer/arrayからcontainer/vectorへ、そして最終的に組み込みスライスへと進化していく過渡期を示しています。

技術的詳細

このコミットの技術的な核心は、container/arrayパッケージの完全な削除と、それに伴う依存関係の更新です。

container/arrayパッケージは、array.goarray_test.gointarray.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.Arraya *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.Newarray.NewIntArrayの呼び出しも、それぞれvector.Newvector.NewIntVectorに置き換えられています。これは、正規表現の内部処理で動的なデータ構造を扱う際に、container/arrayの代わりにcontainer/vectorを使用するように切り替えたことを意味します。

これらの変更は、container/arrayがGo言語の標準ライブラリから完全に排除され、その役割がcontainer/vectorに引き継がれたことを明確に示しています。

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

このコミットのコアとなる変更は、以下のファイルの削除と、container/arrayへの参照をcontainer/vectorに置き換えることです。

  1. 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
    
  2. src/lib/container/array/array.goの削除: (ファイル全体が削除されているため、差分は省略)

  3. src/lib/container/array/array_test.goの削除: (ファイル全体が削除されているため、差分は省略)

  4. src/lib/container/array/intarray.goの削除: (ファイル全体が削除されているため、差分は省略)

  5. src/lib/json/generic.goの変更: arrayパッケージのインポートが削除され、vectorパッケージがインポートされています。 _Array構造体と_JsonBuilder構造体内のarray.Array型がvector.Vector型に置き換えられています。 _JsonBuilderArray()メソッド内で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() {
    
  6. 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/vectorcontainer/arrayの直接的な後継として位置づけられていたことを示しています。container/vectorもまた、interface{}を要素とする動的なコレクションを提供しましたが、その後のGo言語の進化により、最終的には組み込みスライス型がこれらのパッケージの役割を担うことになります。

この変更は、Go言語の設計哲学である「シンプルさ」と「効率性」を追求する姿勢を反映しています。非推奨となったコードを積極的に削除することで、ライブラリの複雑性を減らし、開発者がより推奨されるイディオムやデータ構造に集中できるように促しています。

関連リンク

参考にした情報源リンク