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

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

このコミットは、Go言語の標準ライブラリから testing/script パッケージを削除するものです。このパッケージは、チャネルを使用するコードのテストを支援するために設計されていましたが、「Dead code. (死んだコード)」と判断され、削除されました。これに伴い、関連するドキュメントファイルも更新されています。

コミット

commit cbd6c34131a138c25e33ef038fb7485190637793
Author: Rob Pike <r@golang.org>
Date:   Fri Feb 10 14:31:08 2012 +1100

    testing/script: delete
    Dead code.
    
    Fixes #2961.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/5650053
---
 doc/go1.html                          |  11 ++
 doc/go1.tmpl                          |  11 ++
 src/pkg/testing/script/script.go      | 358 ----------------------------------
 src/pkg/testing/script/script_test.go |  75 -------
 4 files changed, 22 insertions(+), 433 deletions(-)

diff --git a/doc/go1.html b/doc/go1.html
index 0fc7db47c5..c2613aaeab 100644
--- a/doc/go1.html
+++ b/doc/go1.html
@@ -1612,6 +1612,17 @@ Existing code is unaffected, although benchmarks that use <code>println</code>
 or <code>panic</code> should be updated to use the new methods.
 </p>
 
+<h3 id="testing_script">The testing/script package</h3>
+<p>
+The testing/script package has been deleted. It was a dreg.
+</p>
+<p>
+<em>Updating</em>:
+No code is likely to be affected.
+</p>
+
 <h3 id="url">The url package</h3>
 
 <p>
diff --git a/doc/go1.tmpl b/doc/go1.tmpl
index 4a0a283355..0700b3c6d8 100644
--- a/doc/go1.tmpl
+++ b/doc/go1.tmpl
@@ -1502,6 +1502,17 @@ Existing code is unaffected, although benchmarks that use <code>println</code>
 or <code>panic</code> should be updated to use the new methods.
 </p>
 
+<h3 id="testing_script">The testing/script package</h3>
+<p>
+The testing/script package has been deleted. It was a dreg.
+</p>
+<p>
+<em>Updating</em>:
+No code is likely to be affected.
+</p>
+
 <h3 id="url">The url package</h3>
 
 <p>
diff --git a/src/pkg/testing/script/script.go b/src/pkg/testing/script/script.go
deleted file mode 100644
index d8f8093af9..0000000000
--- a/src/pkg/testing/script/script.go
+++ /dev/null
@@ -1,358 +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.
-
-// Package script aids in the testing of code that uses channels.
-package script
-
-import (
-	"fmt"
-	"math/rand"
-	"reflect"
-	"strings"
-)
-
-// An Event is an element in a partially ordered set that either sends a value
-// to a channel or expects a value from a channel.
-type Event struct {
-	name         string
-	occurred     bool
-	predecessors []*Event
-	action       action
-}
-
-type action interface {
-	// getSend returns nil if the action is not a send action.
-	getSend() sendAction
-	// getRecv returns nil if the action is not a receive action.
-	getRecv() recvAction
-	// getChannel returns the channel that the action operates on.
-	getChannel() interface{}
-}
-
-type recvAction interface {
-	recvMatch(interface{}) bool
-}
-
-type sendAction interface {
-	send()
-}
-
-// isReady returns true if all the predecessors of an Event have occurred.
-func (e Event) isReady() bool {
-	for _, predecessor := range e.predecessors {
-		if !predecessor.occurred {
-			return false
-		}
-	}
-
-	return true
-}
-
-// A Recv action reads a value from a channel and uses reflect.DeepMatch to
-// compare it with an expected value.
-type Recv struct {
-	Channel  interface{}
-	Expected interface{}
-}
-
-func (r Recv) getRecv() recvAction { return r }
-
-func (Recv) getSend() sendAction { return nil }
-
-func (r Recv) getChannel() interface{} { return r.Channel }
-
-func (r Recv) recvMatch(chanEvent interface{}) bool {
-	c, ok := chanEvent.(channelRecv)
-	if !ok || c.channel != r.Channel {
-		return false
-	}
-
-	return reflect.DeepEqual(c.value, r.Expected)
-}
-
-// A RecvMatch action reads a value from a channel and calls a function to
-// determine if the value matches.
-type RecvMatch struct {
-	Channel interface{}
-	Match   func(interface{}) bool
-}
-
-func (r RecvMatch) getRecv() recvAction { return r }
-
-func (RecvMatch) getSend() sendAction { return nil }
-
-func (r RecvMatch) getChannel() interface{} { return r.Channel }
-
-func (r RecvMatch) recvMatch(chanEvent interface{}) bool {
-	c, ok := chanEvent.(channelRecv)
-	if !ok || c.channel != r.Channel {
-		return false
-	}
-
-	return r.Match(c.value)
-}
-
-// A Closed action matches if the given channel is closed. The closing is
-// treated as an event, not a state, thus Closed will only match once for a
-// given channel.
-type Closed struct {
-	Channel interface{}
-}
-
-func (r Closed) getRecv() recvAction { return r }
-
-func (Closed) getSend() sendAction { return nil }
-
-func (r Closed) getChannel() interface{} { return r.Channel }
-
-func (r Closed) recvMatch(chanEvent interface{}) bool {
-	c, ok := chanEvent.(channelClosed)
-	if !ok || c.channel != r.Channel {
-		return false
-	}
-
-	return true
-}
-
-// A Send action sends a value to a channel. The value must match the
-// type of the channel exactly unless the channel if of type chan interface{}.
-type Send struct {
-	Channel interface{}
-	Value   interface{}
-}
-
-func (Send) getRecv() recvAction { return nil }
-
-func (s Send) getSend() sendAction { return s }
-
-func (s Send) getChannel() interface{} { return s.Channel }
-
-type empty struct {
-	x interface{}
-}
-
-func newEmptyInterface(e empty) reflect.Value {
-	return reflect.ValueOf(e).Field(0)
-}
-
-func (s Send) send() {
-	// With reflect.ChanValue.Send, we must match the types exactly. So, if
-	// s.Channel is a chan interface{} we convert s.Value to an interface{}
-	// first.
-	c := reflect.ValueOf(s.Channel)
-	var v reflect.Value
-	if iface := c.Type().Elem(); iface.Kind() == reflect.Interface && iface.NumMethod() == 0 {
-		v = newEmptyInterface(empty{s.Value})
-	} else {
-		v = reflect.ValueOf(s.Value)
-	}
-	c.Send(v)
-}
-
-// A Close action closes the given channel.
-type Close struct {
-	Channel interface{}
-}
-
-func (Close) getRecv() recvAction { return nil }
-
-func (s Close) getSend() sendAction { return s }
-
-func (s Close) getChannel() interface{} { return s.Channel }
-
-func (s Close) send() { reflect.ValueOf(s.Channel).Close() }
-
-// A ReceivedUnexpected error results if no active Events match a value
-// received from a channel.
-type ReceivedUnexpected struct {
-	Value interface{}
-	ready []*Event
-}
-
-func (r ReceivedUnexpected) Error() string {
-	names := make([]string, len(r.ready))
-	for i, v := range r.ready {
-		names[i] = v.name
-	}
-	return fmt.Sprintf("received unexpected value on one of the channels: %#v. Runnable events: %s", r.Value, strings.Join(names, ", "))
-}
-
-// A SetupError results if there is a error with the configuration of a set of
-// Events.
-type SetupError string
-
-func (s SetupError) Error() string { return string(s) }
-
-func NewEvent(name string, predecessors []*Event, action action) *Event {
-	e := &Event{name, false, predecessors, action}
-	return e
-}
-
-// Given a set of Events, Perform repeatedly iterates over the set and finds the
-// subset of ready Events (that is, all of their predecessors have
-// occurred). From that subset, it pseudo-randomly selects an Event to perform.
-// If the Event is a send event, the send occurs and Perform recalculates the ready
-// set. If the event is a receive event, Perform waits for a value from any of the
-// channels that are contained in any of the events. That value is then matched
-// against the ready events. The first event that matches is considered to
-// have occurred and Perform recalculates the ready set.
-//
-// Perform continues this until all Events have occurred.
-//
-// Note that uncollected goroutines may still be reading from any of the
-// channels read from after Perform returns.
-//
-// For example, consider the problem of testing a function that reads values on
-// one channel and echos them to two output channels. To test this we would
-// create three events: a send event and two receive events. Each of the
-// receive events must list the send event as a predecessor but there is no
-// ordering between the receive events.
-//
-//  send := NewEvent("send", nil, Send{c, 1})
-//  recv1 := NewEvent("recv 1", []*Event{send}, Recv{c, 1})
-//  recv2 := NewEvent("recv 2", []*Event{send}, Recv{c, 1})
-//  Perform(0, []*Event{send, recv1, recv2})
-//
-// At first, only the send event would be in the ready set and thus Perform will
-// send a value to the input channel. Now the two receive events are ready and
-// Perform will match each of them against the values read from the output channels.
-//
-// It would be invalid to list one of the receive events as a predecessor of
-// the other. At each receive step, all the receive channels are considered,
-// thus Perform may see a value from a channel that is not in the current ready
-// set and fail.
-func Perform(seed int64, events []*Event) (err error) {
-	r := rand.New(rand.NewSource(seed))
-
-	channels, err := getChannels(events)
-	if err != nil {
-		return
-	}
-	multiplex := make(chan interface{})
-	for _, channel := range channels {
-		go recvValues(multiplex, channel)
-	}
-
-Outer:
-	for {
-		ready, err := readyEvents(events)
-		if err != nil {
-			return err
-		}
-
-		if len(ready) == 0 {
-			// All events occurred.
-			break
-		}
-
-		event := ready[r.Intn(len(ready))]
-		if send := event.action.getSend(); send != nil {
-			send.send()
-			event.occurred = true
-			continue
-		}
-
-		v := <-multiplex
-		for _, event := range ready {
-			if recv := event.action.getRecv(); recv != nil && recv.recvMatch(v) {
-				event.occurred = true
-				continue Outer
-			}
-		}
-
-		return ReceivedUnexpected{v, ready}
-	}
-
-	return nil
-}
-
-// getChannels returns all the channels listed in any receive events.
-func getChannels(events []*Event) ([]interface{}, error) {
-	channels := make([]interface{}, len(events))
-
-	j := 0
-	for _, event := range events {
-		if recv := event.action.getRecv(); recv == nil {
-			continue
-		}
-		c := event.action.getChannel()
-		if reflect.ValueOf(c).Kind() != reflect.Chan {
-			return nil, SetupError("one of the channel values is not a channel")
-		}
-
-		duplicate := false
-		for _, other := range channels[0:j] {
-			if c == other {
-				duplicate = true
-				break
-			}
-		}
-
-		if !duplicate {
-			channels[j] = c
-			j++
-		}
-	}
-
-	return channels[0:j], nil
-}
-
-// recvValues is a multiplexing helper function. It reads values from the given
-// channel repeatedly, wrapping them up as either a channelRecv or
-// channelClosed structure, and forwards them to the multiplex channel.
-func recvValues(multiplex chan<- interface{}, channel interface{}) {
-	c := reflect.ValueOf(channel)
-
-	for {
-		v, ok := c.Recv()
-		if !ok {
-			multiplex <- channelClosed{channel}
-			return
-		}
-
-		multiplex <- channelRecv{channel, v.Interface()}
-	}
-}
-
-type channelClosed struct {
-	channel interface{}
-}
-
-type channelRecv struct {
-	channel interface{}
-	value   interface{}
-}
-
-// readyEvents returns the subset of events that are ready.
-func readyEvents(events []*Event) ([]*Event, error) {
-	ready := make([]*Event, len(events))
-
-	j := 0
-	eventsWaiting := false
-	for _, event := range events {
-		if event.occurred {
-			continue
-		}
-
-		eventsWaiting = true
-		if event.isReady() {
-			ready[j] = event
-			j++
-		}
-	}
-
-	if j == 0 && eventsWaiting {
-		names := make([]string, len(events))
-		for _, event := range events {
-			if event.occurred {
-				continue
-			}
-			names[j] = event.name
-		}
-
-		return nil, SetupError("dependency cycle in events. These events are waiting to run but cannot: " + strings.Join(names, ", "))
-	}
-
-	return ready[0:j], nil
-}
diff --git a/src/pkg/testing/script/script_test.go b/src/pkg/testing/script/script_test.go
deleted file mode 100644
index e9ab142c2b..0000000000
--- a/src/pkg/testing/script/script_test.go
+++ /dev/null
@@ -1,75 +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.
-
-package script
-
-import (
-	"testing"
-)
-
-func TestNoop(t *testing.T) {
-	err := Perform(0, nil)
-	if err != nil {
-		t.Errorf("Got error: %s", err)
-	}
-}
-
-func TestSimple(t *testing.T) {
-	c := make(chan int)
-	defer close(c)
-
-	a := NewEvent("send", nil, Send{c, 1})
-	b := NewEvent("recv", []*Event{a}, Recv{c, 1})
-
-	err := Perform(0, []*Event{a, b})
-	if err != nil {
-		t.Errorf("Got error: %s", err)
-	}
-}
-
-func TestFail(t *testing.T) {
-	c := make(chan int)
-	defer close(c)
-
-	a := NewEvent("send", nil, Send{c, 2})
-	b := NewEvent("recv", []*Event{a}, Recv{c, 1})
-
-	err := Perform(0, []*Event{a, b})
-	if err == nil {
-		t.Errorf("Failed to get expected error")
-	} else if _, ok := err.(ReceivedUnexpected); !ok {
-		t.Errorf("Error returned was of the wrong type: %s", err)
-	}
-}
-
-func TestClose(t *testing.T) {
-	c := make(chan int)
-
-	a := NewEvent("close", nil, Close{c})
-	b := NewEvent("closed", []*Event{a}, Closed{c})
-
-	err := Perform(0, []*Event{a, b})
-	if err != nil {
-		t.Errorf("Got error: %s", err)
-	}
-}
-
-func matchOne(v interface{}) bool {
-	if i, ok := v.(int); ok && i == 1 {
-		return true
-	}
-	return false
-}
-
-func TestRecvMatch(t *testing.T) {
-	c := make(chan int)
-
-	a := NewEvent("send", nil, Send{c, 1})
-	b := NewEvent("recv", []*Event{a}, RecvMatch{c, matchOne})
-
-	err := Perform(0, []*Event{a, b})
-	if err != nil {
-		t.Errorf("Got error: %s", err)
-	}
-}

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

https://github.com/golang/go/commit/cbd6c34131a138c25e33ef038fb7485190637793

元コミット内容

testing/script: delete
Dead code.

Fixes #2961.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5650053

変更の背景

このコミットの主な背景は、testing/script パッケージが「Dead code.(死んだコード)」と判断されたことです。Go言語の進化の過程で、このパッケージが提供していた機能が不要になったか、より良い代替手段が提供されたため、維持する必要がなくなったと考えられます。

コミットメッセージにある Fixes #2961 は、Go言語の内部イシュートラッカーにおける課題番号を指している可能性が高いです。Web検索の結果、このコミットの日付(2012年2月)とは無関係な、最近のGo言語の脆弱性(GO-2024-2961 / CVE-2022-30636)がヒットしましたが、これは全く別のものです。したがって、この #2961 は、testing/script パッケージの削除を決定した、当時のGoプロジェクト内部の議論や決定に関連するイシューであると推測されます。

doc/go1.html および doc/go1.tmpl の変更箇所には、「It was a dreg.(それはカスだった)」という記述があり、このパッケージが当初の目的を果たせなかったか、設計上の問題があったことを示唆しています。Go言語はシンプルさと効率性を重視するため、不要になったり、より良い方法が確立されたりしたコードは積極的に削除される傾向にあります。

前提知識の解説

Go言語の並行処理とチャネル

Go言語は、並行処理を言語レベルでサポートしており、その中心的な概念が「ゴルーチン(goroutine)」と「チャネル(channel)」です。

  • ゴルーチン: 軽量なスレッドのようなもので、Goランタイムによって管理されます。数千、数万のゴルーチンを同時に実行しても、オーバーヘッドが非常に小さいのが特徴です。
  • チャネル: ゴルーチン間で値を安全に送受信するための通信メカニズムです。チャネルは、共有メモリによる競合状態(race condition)を避けるための推奨される方法であり、「共有メモリを介して通信するのではなく、通信によってメモリを共有する」というGoの哲学を体現しています。

並行処理のテストの難しさ

並行処理を含むコードのテストは、その非決定性(実行順序が毎回異なる可能性があること)から非常に困難です。

  • タイミングの問題: ゴルーチンの実行タイミングはOSやスケジューラに依存するため、テストが特定のタイミングに依存すると、再現性の低い「flaky test(不安定なテスト)」になりがちです。
  • デッドロック/ライブロック: チャネルの誤った使用は、ゴルーチンが互いに待ち状態になり、プログラムが停止するデッドロックや、処理が進まないライブロックを引き起こす可能性があります。
  • 競合状態: 複数のゴルーチンが同時に共有リソースにアクセスし、予期せぬ結果を生む競合状態も、テストで発見しにくい問題です。

testing/script パッケージの目的(推測)

testing/script パッケージは、削除されたコードから推測するに、このような並行処理のテストの難しさを軽減するために導入されたものと考えられます。特に、チャネルの送受信イベントを「イベント」として抽象化し、それらのイベント間の依存関係(先行イベント)を定義することで、チャネル操作の順序性をある程度制御し、テストの再現性を高めようとしていたようです。

Perform 関数は、定義されたイベントの集合から実行可能なイベントを擬似ランダムに選択し、チャネルの送受信をシミュレートすることで、並行処理のシナリオをテストするフレームワークを提供していました。これにより、開発者はチャネルの挙動をより予測可能な形でテストできることを目指していたのでしょう。

しかし、最終的に「Dead code.」と判断されたことから、このアプローチがGoの並行処理モデルの進化や、よりシンプルで効果的なテスト手法の確立(例えば、sync パッケージの利用や、テストヘルパー関数によるチャネル操作の抽象化など)によって、その役割を終えたか、あるいは設計上の複雑さや使いにくさがあった可能性が考えられます。

技術的詳細

削除された src/pkg/testing/script/script.go のコードから、testing/script パッケージの内部構造と動作を詳細に見ていきます。

主要な型とインターフェース

  • Event 構造体:

    • name: イベントの名前(デバッグ用)。
    • occurred: イベントが発生したかどうかを示すフラグ。
    • predecessors: このイベントが実行される前に発生する必要がある他の Event のスライス。これにより、イベント間の部分的な順序付けを定義します。
    • action: このイベントが実行する具体的なアクション(チャネルの送受信など)を定義するインターフェース。
  • action インターフェース:

    • getSend() sendAction: 送信アクションの場合に sendAction インターフェースを返す。
    • getRecv() recvAction: 受信アクションの場合に recvAction インターフェースを返す。
    • getChannel() interface{}: 操作対象のチャネルを返す。
  • recvAction インターフェース:

    • recvMatch(interface{}) bool: 受信した値が期待されるパターンに一致するかどうかを判定するメソッド。
  • sendAction インターフェース:

    • send(): 値をチャネルに送信するメソッド。

action インターフェースの実装

action インターフェースは、チャネルに対する具体的な操作をカプセル化するために、以下の構造体によって実装されていました。

  • Recv 構造体:

    • Channel interface{}: 受信対象のチャネル。
    • Expected interface{}: 期待される受信値。reflect.DeepEqual を使用して比較されます。
    • recvMatch メソッドで、受信した値が Expected と一致するかをチェックします。
  • RecvMatch 構造体:

    • Channel interface{}: 受信対象のチャネル。
    • Match func(interface{}) bool: 受信した値が期待されるパターンに一致するかを判定するためのカスタム関数。Recv よりも柔軟なマッチングを可能にします。
    • recvMatch メソッドで、Match 関数を呼び出して一致をチェックします。
  • Closed 構造体:

    • Channel interface{}: クローズされたことを期待するチャネル。
    • recvMatch メソッドで、チャネルがクローズされたイベント(channelClosed)を受信したときに一致します。
  • Send 構造体:

    • Channel interface{}: 送信対象のチャネル。
    • Value interface{}: 送信する値。
    • send メソッドで、reflect.ValueOf(s.Channel).Send(v) を使用して値をチャネルに送信します。chan interface{} のような特殊なケースも考慮されていました。
  • Close 構造体:

    • Channel interface{}: クローズ対象のチャネル。
    • send メソッドで、reflect.ValueOf(s.Channel).Close() を使用してチャネルをクローズします。

エラー型

  • ReceivedUnexpected: 予期しない値がチャネルから受信された場合に発生するエラー。
  • SetupError: イベントの設定に問題がある場合に発生するエラー(例: 依存関係の循環)。

Perform 関数

Perform 関数は、testing/script パッケージの核となる部分でした。

func Perform(seed int64, events []*Event) (err error) {
    // ...
}

この関数は、以下のロジックで動作していました。

  1. 乱数シードの初期化: seed を使用して乱数ジェネレータを初期化します。これにより、テストの再現性を確保しつつ、実行可能なイベントの中から擬似ランダムに選択することで、様々な実行パスを探索できます。
  2. チャネルの収集と多重化: getChannels 関数で、すべての受信イベントに関連するチャネルを収集します。その後、これらのチャネルからの受信を多重化するための単一のチャネル (multiplex) を作成し、各チャネルに対して recvValues ゴルーチンを起動します。recvValues は、元のチャネルから値を受信し、それを multiplex チャネルに転送します。
  3. イベントの実行ループ:
    • readyEvents 関数を呼び出して、現在実行可能なイベント(すべての先行イベントが発生済みで、まだ発生していないイベント)のリストを取得します。
    • 実行可能なイベントがない場合、ループを終了します(すべてのイベントが発生したか、デッドロック状態)。
    • 実行可能なイベントの中から、乱数を使って1つをランダムに選択します。
    • 送信イベントの場合: 選択されたイベントが送信アクション (sendAction) であれば、その send() メソッドを呼び出して値を送信し、イベントを「発生済み」としてマークします。
    • 受信イベントの場合: 選択されたイベントが受信アクション (recvAction) であれば、multiplex チャネルから値を受信します。その後、受信した値を実行可能なすべての受信イベントに対して recvMatch メソッドで照合します。最初に一致したイベントを「発生済み」としてマークし、次のループに進みます。
    • どの受信イベントにも一致しない値が受信された場合、ReceivedUnexpected エラーを返します。
  4. デッドロック検出: readyEvents 関数は、実行可能なイベントがないにもかかわらず、まだ発生していないイベントが存在する場合(依存関係の循環など)、SetupError を返してデッドロック状態を検出します。

reflect パッケージの利用

testing/script パッケージは、Goの reflect パッケージを多用していました。これは、チャネルの型が実行時に決定されるため、汎用的なチャネル操作(Send, Recv, Close)を可能にするためです。例えば、Send 構造体の send メソッドでは、reflect.ValueOf(s.Channel).Send(v) を使用して、任意の型のチャネルに値を送信していました。

削除の理由の推測

このパッケージが削除された理由としては、以下のような点が考えられます。

  • 複雑性: EventactionRecvSend などの抽象化レイヤーが、Goのシンプルさを損なっていた可能性があります。特に reflect パッケージの多用は、コードの可読性やパフォーマンスに影響を与えることがあります。
  • Goのテストフレームワークの成熟: Goの標準 testing パッケージや、よりシンプルなテストヘルパー関数、sync パッケージの利用など、Goの並行処理テストの手法が成熟し、testing/script が提供する機能が不要になった。
  • 実用性の欠如: 実際の複雑な並行処理のシナリオをテストする上で、このフレームワークが期待されたほど効果的ではなかった、あるいは使いにくかった。
  • 「dreg」の判断: ドキュメントに「It was a dreg.(それはカスだった)」と明記されていることから、設計思想や実装に根本的な問題があった可能性も示唆されます。

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

このコミットでは、以下の4つのファイルが変更されています。

  1. doc/go1.html: Go 1のリリースノートHTMLファイル。
    • testing/script パッケージが削除されたことを示すセクションが追加されました。
    • 追加された行: 11行
  2. doc/go1.tmpl: doc/go1.html のテンプレートファイル。
    • doc/go1.html と同様に、testing/script パッケージの削除に関する記述が追加されました。
    • 追加された行: 11行
  3. src/pkg/testing/script/script.go: testing/script パッケージの主要な実装ファイル。
    • ファイル全体が削除されました。
    • 削除された行: 358行
  4. src/pkg/testing/script/script_test.go: testing/script パッケージのテストファイル。
    • ファイル全体が削除されました。
    • 削除された行: 75行

合計で22行が追加され、433行が削除されており、これは主に testing/script パッケージとそのテストコードの完全な削除によるものです。

コアとなるコードの解説

このコミットの「コアとなるコードの変更」は、実質的に src/pkg/testing/script/script.gosrc/pkg/testing/script/script_test.go削除です。

  • src/pkg/testing/script/script.go の削除:

    • このファイルには、testing/script パッケージのすべてのロジック、データ構造、および Perform 関数が実装されていました。このファイルの削除は、このパッケージが提供していた並行処理テストのフレームワークが、Go言語の標準ライブラリから完全に廃止されたことを意味します。
    • これにより、このパッケージに依存していた可能性のある既存のコードは、コンパイルエラーとなるか、代替のテスト手法に移行する必要が生じます。ただし、コミットメッセージやドキュメントの更新内容から、「No code is likely to be affected.(影響を受けるコードはほとんどないだろう)」とされているため、このパッケージが広く利用されていたわけではないことが示唆されます。
  • src/pkg/testing/script/script_test.go の削除:

    • このファイルには、testing/script パッケージ自体のテストコードが含まれていました。パッケージが削除されたため、そのテストコードも不要となり、同時に削除されました。
  • doc/go1.html および doc/go1.tmpl の更新:

    • これらのドキュメントファイルは、Go 1のリリースに関する情報を提供していました。testing/script パッケージが削除されたことを明記するために、新しいセクションが追加されました。
    • このドキュメントの更新は、Go 1の公式リリースノートの一部として、この変更がユーザーに通知されることを保証します。特に「It was a dreg.」という表現は、このパッケージがGo開発チームによって失敗作と見なされていたことを率直に示しています。

これらの変更は、Go言語の標準ライブラリが、その設計哲学であるシンプルさと効率性を追求し、不要な複雑性や機能を取り除くために継続的に改善されていることを示しています。

関連リンク

参考にした情報源リンク