メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

新機能

go/token パッケージの File 型に、ファイル名と位置範囲を含む簡潔な説明を返す String メソッドを追加した。

go/token

この項目の注釈は AI により生成されており、誤りを含む場合があります。
使用例のコンパイル検証: 検証済み

概要

go/token パッケージの File 型に fmt.Stringer を実装する String メソッドが追加された。これまで *Filefmt.Println 等でそのまま出力すると、非公開フィールドを含む構造体の生ダンプ(大規模ファイルでは巨大な行オフセットテーブルまで含む)が表示されてしまっていたが、今後はファイル名と位置範囲(Base〜End)からなる簡潔な説明が得られるようになる。

導入経緯

提案者の @adonovan は、Issue #76285token.NewFileSet().AddFile(...) の結果を fmt.Println した際に内部構造がそのままダンプされてしまう問題を指摘し、String メソッドの追加を提案した。当初はファイル名のみを返す案だったが、レビューで「Name() を直接呼べばよいのでは」という指摘を受け、位置範囲(Base〜End)も含む "%s(%d-%d)" 形式に改められた。関連する Issue #75849(*File).End() メソッドの追加)が先行して実装されており、本提案の String はその End() を利用している。

議論タイムライン

議論のハイライト

  • String の出力内容について、当初案の「ファイル名のみ」に対し、レビュアーから「ファイル名だけなら Name() を直接呼べばよい」との指摘があり、より情報量の多いフォーマットへ改められた。
  • 出力フォーマットをどこまで詳細にすべきかという議論もあったが、最終的には「人間が読める簡潔な説明」とし、実装の細部は実装者の裁量に委ねる方向で収束した。
  • fmt.GoStringer%#v 用)を別途実装する案も出たが、本提案では採用されなかった。

使用例

Before

package main

import (
	"fmt"
	"go/token"
)

func main() {
	fset := token.NewFileSet()
	f := fset.AddFile("foo.go", -1, 100)
	fmt.Println(f)
	// 出力: &{foo.go 1 100 {{} {0 0}} [0] []}
}

After

package main

import (
	"fmt"
	"go/token"
)

func main() {
	fset := token.NewFileSet()
	f := fset.AddFile("foo.go", -1, 100)
	fmt.Println(f)
	// 出力: foo.go(1-101)
}

実装解説

実装(go/token/position.go)は次の通りで、提案時のコードのまま採用されている。

func (f *File) String() string {
	return fmt.Sprintf("%s(%d-%d)", f.Name(), f.Base(), f.End())
}

Name()Base()End() はいずれも既存の公開メソッドで、End() は関連提案 #75849 で追加されたものを利用している。新たな状態やフィールドは持たず、既存の情報を組み合わせて文字列化するだけの薄いメソッドである。

関連リンク