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

Go Proposal Weekly Digest

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

新機能

strings/bytesパッケージに、末尾から最後のセパレータで文字列を分割するCutLast関数を追加する

strings

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

概要

stringsパッケージおよびbytesパッケージにCutLast関数が追加される。既存のstrings.Cutがセパレータの最初の出現位置で文字列を分割するのに対し、CutLastはセパレータの最後の出現位置で分割する。セパレータが見つからない場合はs, "", falseを返す仕様であり、これはCutが見つからない場合にs, "", falseを返すのと対称的な設計である。内部的にはstrings.LastIndexを使った実装に相当する。

導入経緯

提案者は、文字列を末尾側から分割する処理(package-url仕様の一部パースなど)のために自作のCutLast関数を何度も書く必要があったことを動機として挙げている。議論の中で@rogpeppeは自身のコードベース内だけで少なくとも5つの同等の独自実装を発見したと報告しており、標準ライブラリでの提供に対する支持が広がった。

議論タイムライン

  • 2026-03-25: Proposal Review Meetingで議題(active)として追加された。
  • 2026-04-08: Proposal Review Meetingで likely accept と判定された。
  • 2026-04-16: 前回ミーティングからコンセンサスに変化がないことが確認され、accepted となった。

議論のハイライト

  • 関数名はLastIndexとの一貫性を重視したLastCut案と、CutXファミリーへの帰属を重視したCutLast案が議論され、最終的にCutLastが採用された。
  • 最大の争点は、セパレータが見つからない場合の戻り値である。@rogpeppeは自身が逆のセマンティクス("", s, false)で実装した関数を、実際にはbefore側に完全な文字列が入る前提のコードで誤用していたことを報告し、s, "", false(Cutと対称的な仕様)を支持する実証的な根拠となった。
  • CutSuffixとの混同が懸念されたが、戻り値の型が異なる(CutLastは3値、CutSuffixは2値)ため、実際の誤用は少ないと判断された。
  • 実装のCLが誤って自動マージ可能な状態になっており、コメント期間中に取り込まれてしまうという経緯があったが、その後のミーティングでコンセンサスに変化がないことが確認され、正式に承認された。

使用例

Before

package main

import (
	"fmt"
	"strings"
)

func cutLast(s, sep string) (before, after string, found bool) {
	if i := strings.LastIndex(s, sep); i >= 0 {
		return s[:i], s[i+len(sep):], true
	}
	return s, "", false
}

func main() {
	dir, file, ok := cutLast("/usr/local/bin/go", "/")
	fmt.Println(dir, file, ok)
}

After

package main

import (
	"fmt"
	"strings"
)

func main() {
	dir, file, ok := strings.CutLast("/usr/local/bin/go", "/")
	fmt.Println(dir, file, ok)
}

実装解説

strings.CutLaststrings.go:1291で定義されており、LastIndexでセパレータの最後の出現位置を求め、見つかった場合はその前後で文字列を分割し、見つからない場合は元の文字列全体をbeforeとして返す。bytes.CutLastbytes.go:1430に同様のロジックで実装されている。

関連リンク