[インデックス 11093] ファイルの概要
このコミットは、Go言語の標準ライブラリimage
パッケージにおいて、image.Tiled
という型および関連する関数名をimage.Repeated
にリネームする変更を導入しています。この変更の主な目的は、既存のTiled
の実装が「小さな画像を繰り返して大きな画像を構成する」という特定の機能に限定されているため、その実態をより正確に反映する名前に変更することです。これにより、将来的に「タイリング」というより広範な概念(例: Google Mapsのような異なるタイルを組み合わせる、巨大な画像を部分的に表示する)を扱うためのimage.Tiled
という名前を温存しています。
このリネームは、gofix
ツールによって自動的にコードベース全体に適用されるように、gofix
の新しい修正ルールも追加されています。
コミット
Author: Nigel Tao nigeltao@golang.org Date: Wed Jan 11 12:35:05 2012 +1100
image: rename image.Tiled to image.Repeated.
What package image currently provides is a larger image consisting
of many copies of a smaller image.
More generally, a tiled image could be a quilt consisting of different
smaller images (like Google Maps), or a technique to view a portion of
enormous images without requiring the whole thing in memory.
This richer construct might not ever belong in the standard library (and
is definitely out of scope for Go 1), but I would like the option for
image.Tiled to be its name.
R=r, rsc
CC=golang-dev
https://golang.org/cl/5530062
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/415f15b66746d8e0cd6f01e89dceed41e617be5f
元コミット内容
image: rename image.Tiled to image.Repeated.
What package image currently provides is a larger image consisting
of many copies of a smaller image.
More generally, a tiled image could be a quilt consisting of different
smaller images (like Google Maps), or a technique to view a portion of
enormous images without requiring the whole thing in memory.
This richer construct might not ever belong in the standard library (and
is definitely out of scope for Go 1), but I would like the option for
image.Tiled to be its name.
R=r, rsc
CC=golang-dev
https://golang.org/cl/5530062
変更の背景
この変更の背景には、Go言語のimage
パッケージにおけるAPI設計の意図と、将来的な拡張性への配慮があります。
元々image.Tiled
という名前で提供されていた機能は、実際には「単一の小さな画像を無限に繰り返して大きな仮想画像を生成する」というものでした。しかし、「タイリング(tiling)」という言葉は、画像処理の文脈においてより広範な意味を持つことがあります。例えば、Google Mapsのように異なる複数の画像を組み合わせて全体像を形成する「モザイク画像」や、非常に大きな画像をメモリに全て読み込むことなく部分的に表示するための「タイルベースの画像処理」といった概念が含まれます。
コミットメッセージにあるように、現在のimage.Tiled
の実装は、これらのよりリッチな「タイリング」の概念とは異なり、単なる「繰り返し」に過ぎません。そのため、API名がその機能の実態と乖離しているという問題がありました。
この乖離を解消し、APIのセマンティクスをより明確にするために、image.Tiled
はimage.Repeated
にリネームされました。これにより、image.Tiled
という名前は、将来的にGoの標準ライブラリでより汎用的なタイリング機能が導入される可能性に備えて、予約された状態になります。Go 1のスコープ外ではあるものの、将来的な拡張性を考慮した、API設計における先見の明を示す変更と言えます。
前提知識の解説
Go言語のimage
パッケージ
Go言語の標準ライブラリには、画像処理のためのimage
パッケージが含まれています。このパッケージは、様々な画像フォーマット(PNG, JPEGなど)の読み書き、画像の生成、操作、変換といった基本的な機能を提供します。
image.Image
インターフェース:image
パッケージの中心となるのはImage
インターフェースです。これは、ColorModel() color.Model
、Bounds() Rectangle
、At(x, y int) color.Color
という3つのメソッドを定義しており、これにより任意の画像データを抽象的に扱うことができます。ColorModel()
: 画像の色の表現方法(例: RGBA、グレースケール)を返します。Bounds()
: 画像のピクセル座標における境界(長方形)を返します。At(x, y int)
: 指定された座標のピクセルの色を返します。
image.Point
とimage.Rectangle
: 画像内の座標や領域を表すための基本的な型です。color.Color
: 色を表すインターフェースで、RGBA()
メソッドを持ちます。
このコミットで変更されるTiled
(変更後はRepeated
)は、このimage.Image
インターフェースを実装しており、あたかも無限に広がる画像であるかのように振る舞います。
gofix
ツール
gofix
は、Go言語のソースコードを自動的に修正するためのコマンドラインツールです。Go言語のAPIが変更されたり、言語仕様が更新されたりした場合に、古いコードを新しいAPIや仕様に準拠させるために使用されます。
gofix
は、Goのソースコードを抽象構文木(AST: Abstract Syntax Tree)として解析し、定義された「修正ルール(fix rule)」に基づいてASTを変換することでコードを書き換えます。これにより、開発者は手動で大量のコードを修正する手間を省き、APIの変更に迅速に対応できます。
このコミットでは、image.Tiled
からimage.Repeated
へのリネームというAPI変更に対応するため、新しいgofix
の修正ルールが追加されています。
画像処理における「タイリング」と「繰り返し」
- 繰り返し (Repeating): 単一の画像を、水平方向および垂直方向に単純に並べて、より大きな(あるいは無限の)画像を生成する手法です。同じパターンが連続して現れるため、テクスチャや背景などに利用されます。このコミットで
image.Repeated
が指すのはこの概念です。 - タイリング (Tiling): より広範な概念で、複数の異なる画像(タイル)を組み合わせて、より大きな画像を構成する手法を指します。
- モザイク画像: 異なる内容の小さな画像を並べて、全体として一つの大きな画像を表現する。
- 巨大画像の表示: Google Mapsのように、非常に大きな画像を小さな領域(タイル)に分割し、必要な部分だけを読み込んで表示することで、メモリ使用量を抑えつつ効率的に画像を扱う手法。
- テクスチャアトラス: ゲーム開発などで、複数の小さなテクスチャを一枚の大きな画像にまとめておく手法。
image.Tiled
という名前は、後者のより複雑で汎用的なタイリングの概念を想起させるため、現在のimage
パッケージの実装(単なる繰り返し)とは意味合いが異なっていました。この乖離が、今回のリネームの動機となっています。
技術的詳細
このコミットの技術的詳細は、主に以下の2つの側面から構成されます。
-
image
パッケージ内のAPI名称変更:src/pkg/image/names.go
ファイルにおいて、Tiled
という名前の型、そのレシーバメソッド、およびコンストラクタ関数がRepeated
に一括して変更されています。これは、APIのセマンティクスをより正確に反映させるための直接的な変更です。type Tiled struct
がtype Repeated struct
に変更。func (t *Tiled)
のレシーバ変数名がt
からr
に変更され、型も*Repeated
に変更。func NewTiled
がfunc NewRepeated
に変更。- 関連するコメントも
Tiled
からRepeated
に更新されています。
-
gofix
ツールの修正ルールの追加: このAPI名称変更は、既存のGoコードベースに影響を与えるため、gofix
ツールが自動的にコードを修正できるように新しいルールが追加されました。src/cmd/gofix/imagetiled.go
が新規作成され、image.Tiled
をimage.Repeated
にリネームするgofix
の修正ロジックが実装されています。- このファイルでは、GoのAST(抽象構文木)を走査し、
image.Tiled
という形式のセレクタ式(例:image.Tiled{...}
やvar _ image.Tiled
)を見つけると、そのTiled
の部分をRepeated
に書き換える処理が行われます。 src/cmd/gofix/imagetiled_test.go
も新規作成され、このgofix
ルールが正しく機能するかどうかを検証するためのテストケースが記述されています。テストケースは、入力コード(In
)と期待される出力コード(Out
)のペアで構成され、image.Tiled
がimage.Repeated
に変換されることを確認します。src/cmd/gofix/Makefile
に、新しく追加されたimagetiled.go
がgofix
のビルド対象に含まれるように変更が加えられています。
このアプローチにより、Go言語のAPI変更がユーザーのコードベースに与える影響を最小限に抑えつつ、スムーズな移行を可能にしています。gofix
は、Go言語の進化において重要な役割を果たすツールであり、このようなAPIリネームの自動化はその典型的なユースケースです。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。
src/pkg/image/names.go
このファイルは、image
パッケージ内で定義されている様々な画像関連の型やコンストラクタ関数を含んでいます。
--- a/src/pkg/image/names.go
+++ b/src/pkg/image/names.go
@@ -51,25 +51,25 @@ func NewUniform(c color.Color) *Uniform {
return &Uniform{c}
}
-// A Tiled is an infinite-sized Image that repeats another Image in both
-// directions. Tiled{i, p}.At(x, y) will equal i.At(x+p.X, y+p.Y) for all
+// Repeated is an infinite-sized Image that repeats another Image in both
+// directions. Repeated{i, p}.At(x, y) will equal i.At(x+p.X, y+p.Y) for all
// points {x+p.X, y+p.Y} within i\'s Bounds.
-type Tiled struct {
+type Repeated struct {
I Image
Offset Point
}
-func (t *Tiled) ColorModel() color.Model {\n-\treturn t.I.ColorModel()\n+func (r *Repeated) ColorModel() color.Model {\n+\treturn r.I.ColorModel()\n }
-func (t *Tiled) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }\n+func (r *Repeated) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }\n
-func (t *Tiled) At(x, y int) color.Color {\n-\tp := Point{x, y}.Add(t.Offset).Mod(t.I.Bounds())\n-\treturn t.I.At(p.X, p.Y)\n+func (r *Repeated) At(x, y int) color.Color {\n+\tp := Point{x, y}.Add(r.Offset).Mod(r.I.Bounds())\n+\treturn r.I.At(p.X, p.Y)\n }
-func NewTiled(i Image, offset Point) *Tiled {\n-\treturn &Tiled{i, offset}\n+func NewRepeated(i Image, offset Point) *Repeated {\n+\treturn &Repeated{i, offset}\n }
src/cmd/gofix/imagetiled.go
(新規追加)
このファイルは、gofix
ツールがimage.Tiled
をimage.Repeated
に自動修正するためのロジックを実装しています。
// Copyright 2012 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 main
import (
"go/ast"
)
func init() {
register(imagetiledFix)
}
var imagetiledFix = fix{
"imagetiled",
"2012-01-10",
imagetiled,
`Rename image.Tiled to image.Repeated.
http://codereview.appspot.com/5530062
`,
}
func imagetiled(f *ast.File) bool {
if !imports(f, "image") {
return false
}
fixed := false
walk(f, func(n interface{}) {
s, ok := n.(*ast.SelectorExpr)
if !ok || !isTopName(s.X, "image") || s.Sel.String() != "Tiled" {
return
}
s.Sel = &ast.Ident{Name: "Repeated"} // ここがTiledをRepeatedに書き換える核心部分
fixed = true
})
return fixed
}
src/cmd/gofix/imagetiled_test.go
(新規追加)
このファイルは、gofix
のimagetiled
修正が正しく機能するかを検証するためのテストケースを含んでいます。
// Copyright 2012 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 main
func init() {
addTestCases(imagetiledTests, imagetiled)
}
var imagetiledTests = []testCase{
{
Name: "imagetiled.0",
In: `package main
import (
"foo"
"image"
)
var (
_ foo.Tiled
_ image.RGBA
_ image.Tiled // この行が修正対象
)
`,
Out: `package main
import (
"foo"
"image"
)
var (
_ foo.Tiled
_ image.RGBA
_ image.Repeated // この行が修正後
)
`,
},
}
コアとなるコードの解説
src/pkg/image/names.go
の変更
このファイルにおける変更は、image
パッケージの公開APIの名称を直接変更するものです。
type Tiled struct
からtype Repeated struct
:Tiled
という構造体名がRepeated
に変更されました。これにより、この型が表現する「画像を繰り返す」という機能がより明確になります。- レシーバメソッドの変更:
func (t *Tiled)
のようにTiled
型をレシーバとするメソッドも、func (r *Repeated)
のようにRepeated
型をレシーバとするように変更されました。レシーバ変数名も慣習に従いt
からr
に変更されています。これらのメソッド(ColorModel
,Bounds
,At
)は、image.Image
インターフェースの実装であり、Repeated
型が画像として振る舞うためのものです。 - コンストラクタ関数の変更:
func NewTiled
がfunc NewRepeated
に変更されました。これは、新しいRepeated
型のインスタンスを生成するための公開関数です。
これらの変更は、image
パッケージのAPIがその機能とセマンティクスをより正確に表現するように改善されたことを意味します。
src/cmd/gofix/imagetiled.go
のimagetiled
関数
この関数は、gofix
ツールの中核をなす部分であり、Goのソースコードを解析し、特定のパターンに合致するコードを自動的に書き換えます。
imports(f, "image")
: まず、処理対象のファイルf
が"image"
パッケージをインポートしているかどうかを確認します。image
パッケージを使用していないファイルは、この修正の対象外となるため、無駄な処理を避けることができます。walk(f, func(n interface{}) {...})
:walk
関数は、GoのAST(抽象構文木)を深さ優先で走査するためのユーティリティです。ASTの各ノードn
に対して、無名関数が実行されます。s, ok := n.(*ast.SelectorExpr)
: 現在のASTノードn
が*ast.SelectorExpr
型(セレクタ式、例:image.Tiled
のimage.Tiled
全体)であるかをチェックします。!ok || !isTopName(s.X, "image") || s.Sel.String() != "Tiled"
:!ok
:*ast.SelectorExpr
型でなければスキップします。!isTopName(s.X, "image")
: セレクタ式の左側(s.X
、例:image.Tiled
のimage
部分)が"image"
という名前の識別子でなければスキップします。これにより、foo.Tiled
のような他のパッケージのTiled
という名前には影響を与えません。s.Sel.String() != "Tiled"
: セレクタ式の右側(s.Sel
、例:image.Tiled
のTiled
部分)が"Tiled"
という文字列でなければスキップします。 これらの条件を全て満たす場合、それはimage.Tiled
というパターンに合致するコードであると判断されます。
s.Sel = &ast.Ident{Name: "Repeated"}
: ここがこの修正の核心部分です。image.Tiled
のTiled
という識別子を、新しいRepeated
という識別子に書き換えます。これにより、ASTが変更され、最終的に新しいコードが生成されます。fixed = true
: 修正が行われたことを示すフラグを立てます。return fixed
: 修正が行われた場合はtrue
を返し、gofix
ツールにファイルが変更されたことを伝えます。
このimagetiled
関数は、GoのAST操作の典型的な例であり、コンパイラやコード分析ツール、自動リファクタリングツールなどで広く用いられる技術です。
src/cmd/gofix/imagetiled_test.go
のテストケース
このテストファイルは、imagetiled
修正が意図通りに動作することを保証します。
addTestCases(imagetiledTests, imagetiled)
:imagetiledTests
というテストケースのスライスをimagetiled
関数に関連付けて登録します。testCase
構造体: 各テストケースはName
(テストケース名)、In
(入力となるGoのソースコード)、Out
(gofix
適用後に期待されるGoのソースコード)で構成されます。- テストの目的: 提供されたテストケースでは、
var _ image.Tiled
という行がvar _ image.Repeated
に正しく変換されることを確認しています。これにより、gofix
がユーザーのコードベースでimage.Tiled
の使用箇所を正確に特定し、image.Repeated
に書き換える能力があることが検証されます。
このようなテストの存在は、自動コード修正ツールの信頼性を高める上で不可欠です。
関連リンク
- Go Code Review: https://golang.org/cl/5530062
参考にした情報源リンク
- Go言語公式ドキュメント:
image
パッケージ (https://pkg.go.dev/image) - Go言語公式ドキュメント:
go/ast
パッケージ (https://pkg.go.dev/go/ast) - Go言語公式ドキュメント:
gofix
コマンド (Goのバージョンによってドキュメントの場所が異なる場合がありますが、通常はGoのツールに関するセクションに記載されています。)- Go 1.xのドキュメント:
go help fix
またはgo doc cmd/gofix
で詳細を確認できます。
- Go 1.xのドキュメント: