strings
strings パッケージは UTF-8 エンコードされた文字列を操作するシンプルな関数を実装します。簡単に言えば、文字列操作のためのユーティリティパッケージです。
公式ドキュメント:strings package - strings - Go Packages
TIP
Go はネイティブで UTF8 文字をサポートしており、すべての文字列操作は UTF8 に基づいて構築されています。
インポート
import (
"strings"
)以下では例を使用して一般的な関数を説明します。
文字列の複製
func Clone(s string) string複製されたコピー用に新しいメモリを割り当てます。空の文字列を渡した場合、メモリは割り当てられず、空の文字列が返されます。
func TestClone(t *testing.T) {
ori := "hello 世界"
copys := strings.Clone(ori)
fmt.Println(ori, copys)
fmt.Println(&ori, ©s)
}=== RUN TestClone
hello 世界 hello 世界
0xc00005e5d0 0xc00005e5e0
--- PASS: TestClone (0.00s)
PASS文字列の比較
func Compare(a, b string) inta と b を辞書順で文字列比較します。a>b の場合 1 を返し、a<b の場合 -1 を返し、a=b の場合 0 を返します。
func TestCompare(t *testing.T) {
fmt.Println(strings.Compare("abc", "abe"))
fmt.Println(strings.Compare("abcd", "abe"))
fmt.Println(strings.Compare("abijk", "abe"))
fmt.Println(strings.Compare("abe", "abe"))
}=== RUN TestCompare
-1
-1
1
0
--- PASS: TestCompare (0.00s)
PASS文字列の包含
func Contains(s, substr string) bool文字列 s が部分文字列 substr を含んでいるかどうかを判断します。
func TestContains(t *testing.T) {
fmt.Println(strings.Contains("abcdefg", "a"))
fmt.Println(strings.Contains("abcdefg", "abc"))
fmt.Println(strings.Contains("abcdefg", "ba"))
}=== RUN TestContains
true
true
false
--- PASS: TestContains (0.00s)
PASSfunc ContainsAny(s, chars string) bool文字列 chars 内の任意の文字の Unicode コードが文字列 s 内にあるかどうかを判断します。つまり、s が chars 内の任意の文字列を含んでいるかどうかを判断します。
func TestContainsAny(t *testing.T) {
fmt.Println(strings.ContainsAny("abcedfg", "bac"))
fmt.Println(strings.ContainsAny("abcedfg", "gfdecba"))
}=== RUN TestContainsAny
true
--- PASS: TestContainsAny (0.00s)
PASSfunc ContainsRune(s string, r rune) bool文字列 s が文字 r を含んでいるかどうかを判断します。
func TestContainsRune(t *testing.T) {
fmt.Println(strings.ContainsRune("abcedf", 'a'))
fmt.Println(strings.ContainsRune("abcedf", 'b'))
fmt.Println(strings.ContainsRune("你好世界", '你'))
}=== RUN TestContainsRune
true
true
true
--- PASS: TestContainsRune (0.00s)
PASS部分文字列の出現回数
func Count(s, substr string) int部分文字列 substr が文字列 s 内に出現する回数を返します。
func TestCount(t *testing.T) {
fmt.Println(strings.Count("3.1415926", "1"))
fmt.Println(strings.Count("there is a girl", "e"))
fmt.Println(strings.Count("there is a girl", ""))
}=== RUN TestCount
2
2
16
--- PASS: TestCount (0.00s)
PASS指定された部分文字列の削除
func Cut(s, sep string) (before, after string, found bool)s 内で最初に出現する部分文字列 sep を削除し、削除後の結果を返します。
before- 削除された部分文字列の前の文字列after- 削除された部分文字列の後の文字列found- 部分文字列が見つかったかどうか
func TestCut(t *testing.T) {
show := func(s, sep string) {
before, after, found := strings.Cut(s, sep)
fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found)
}
show("Hello world", " ")
show("Hello world", "world")
show("Hello world", "Hello")
show("Hello world", "Hello world")
}=== RUN TestCut
Cut("Hello world", " ") = "Hello", "world", true
Cut("Hello world", "world") = "Hello ", "", true
Cut("Hello world", "Hello") = "", " world", true
Cut("Hello world", "Hello world") = "", "", true
--- PASS: TestCut (0.00s)
PASS大文字小文字を無視した等価比較
func EqualFold(s, t string) bool文字列 s と t が大文字小文字を無視して等しいかどうかを返します。
func TestEqualFold(t *testing.T) {
fmt.Println(strings.EqualFold("你好", "你好"))
fmt.Println(strings.EqualFold("Hello", "Hello"))
fmt.Println(strings.EqualFold("Hello", "hELLO"))
}=== RUN TestEqualFold
true
true
true
--- PASS: TestEqualFold (0.00s)
PASS文字列の分割
func Fields(s string) []stringfunc FieldsFunc(s string, f func(rune) bool) []string前者はスペースに基づいて文字列を分割し、後者は関数 f の戻り値に基づいて文字列を分割するかどうかを決定します。
func TestField(t *testing.T) {
fmt.Printf("%q\n", strings.Fields(" a b c d e f g "))
fmt.Printf("%q\n", strings.FieldsFunc("a,b,c,d,e,f,g", func(r rune) bool {
return r == ','
}))
}=== RUN TestField
["a" "b" "c" "d" "e" "f" "g"]
["a" "b" "c" "d" "e" "f" "g"]
--- PASS: TestField (0.00s)
PASS接頭辞・接尾辞の検索
func HasPrefix(s, prefix string) boolfunc HasSuffix(s, suffix string) bool前者は接頭辞を検索し、後者は接尾辞を検索します。興味がある方はソースコードの実装をご覧ください。巧妙な実装です。
func TestPreSuffix(t *testing.T) {
str := "abbc cbba"
fmt.Println(strings.HasPrefix(str, "abb"))
fmt.Println(strings.HasSuffix(str, "bba"))
}=== RUN TestPreSuffix
true
true
--- PASS: TestPreSuffix (0.00s)
PASS部分文字列の位置
最初に出現する部分文字列のインデックスを返します。
func Index(s, substr string) int最初に出現する部分文字列のインデックスを返します。
func IndexAny(s, chars string) int最初に出現する部分文字列のインデックスを返します。
func IndexRune(s string, r rune) int例
func TestIndex(t *testing.T) {
fmt.Println(strings.Index("abcdefg", "bc"))
fmt.Println(strings.IndexAny("abcdefg", "cb"))
fmt.Println(strings.IndexRune("abcdefg", 'g'))
}=== RUN TestIndex
1
1
6
--- PASS: TestIndex (0.00s)
PASS最後に出現する部分文字列のインデックスを返します。
func LastIndex(s, substr string) int最後に出現する部分文字列の任意の文字のインデックスを返します。
func LastIndexAny(s, chars string) int例
func TestLastIndex(t *testing.T) {
fmt.Println(strings.LastIndex("abcdefga", "a"))
fmt.Println(strings.LastIndexAny("abcdefghisa", "ba"))
}文字列の走査・置換
Map は文字列 s のコピーを返し、マッピング関数に基づいて文字列 s のすべての文字を変更します。マップが負の値を返す場合、その文字は文字列から削除され、置換されません。
func Map(mapping func(rune) rune, s string) string例
func TestMap(t *testing.T) {
fmt.Println(strings.Map(func(r rune) rune {
return r - 32
}, "abcdefghijk"))
fmt.Println(strings.Map(func(r rune) rune {
return r + 32
}, "ABCDEFGHIJK"))
fmt.Println(strings.Map(func(r rune) rune {
if r < 'F' {
return -1
} else {
return r
}
}, "ABCDEFGHIJK"))
}出力
=== RUN TestMap
ABCDEFGHIJK
abcdefghijk
FGHIJK
--- PASS: TestMap (0.00s)
PASS文字列の複製
指定された Count に基づいて文字列を複製します。負の数の場合、panic になります。
func Repeat(s string, count int) string例
func TestRepeat(t *testing.T) {
fmt.Println(strings.Repeat("a", 10))
fmt.Println(strings.Repeat("abc", 10))
}出力
=== RUN TestRepeat
aaaaaaaaaa
abcabcabcabcabcabcabcabcabcabc
--- PASS: TestRepeat (0.00s)
PASS文字列の置換
s は元の文字列、old は置換される部分、new は old の置換部分、n は置換回数を示します。n が 0 未満の場合、置換回数は制限されません。
func Replace(s, old, new string, n int) string例
func TestReplace(t *testing.T) {
fmt.Println(strings.Replace("Hello this is golang", "golang", "c++", 1))
fmt.Println(strings.Replace("Hello this is golang", "o", "c", -1))
fmt.Println(strings.Replace("Hello this is golang", "o", "c", 1))
}出力
=== RUN TestReplace
Hello this is c++
Hellc this is gclang
Hellc this is golang
--- PASS: TestReplace (0.00s)
PASSReplace のユーティリティ関数で、stings.Replace(s,old,new,-1) と等価です。
func ReplaceAll(s, old, new string) string例
func TestReplaceAll(t *testing.T) {
fmt.Println(strings.ReplaceAll("Hello this is golang", "o", "c++"))
}出力
=== RUN TestReplaceAll
Hellc++ this is gc++lang
--- PASS: TestReplaceAll (0.00s)
PASS文字列の分割
部分文字列 sep に基づいて文字列 s を文字列スライスに分割します。
func Split(s, sep string) []string部分文字列 sep に基づいて文字列 s を文字列スライスに分割します。分割回数は n によって決定されます。
func SplitN(s, sep string, n int) []string部分文字列 sep に基づいて文字列 s を sep を含む文字列要素で構成された文字列スライスに分割します。
func SplitAfter(s, sep string) []string部分文字列 sep に基づいて文字列 s を sep を含む文字列要素で構成された文字列スライスに分割します。分割回数は n によって決定されます。
func SplitAfterN(s, sep string, n int) []string例
func TestSplit(t *testing.T) {
fmt.Printf("%q\n", strings.Split("this is go language", " "))
fmt.Printf("%q\n", strings.SplitN("this is go language", " ", 2))
fmt.Printf("%q\n", strings.SplitAfter("this is go language", " "))
fmt.Printf("%q\n", strings.SplitAfterN("this is go language", " ", 2))
}出力
=== RUN TestSplit
["this" "is" "go" "language"]
["this" "is go language"]
["this " "is " "go " "language"]
["this " "is go language"]
--- PASS: TestSplit (0.00s)
PASS大文字小文字の変換
英字文字列を小文字に変換します。
func ToLower(s string) string対応する言語の unicode.SpecialCase に基づいて、対応する言語の小文字に変換します。
func ToLowerSpecial(c unicode.SpecialCase, s string) string英字文字列を大文字に変換します。
func ToUpper(s string) string対応する言語の unicode.SpecialCase に基づいて、対応する言語の大文字に変換します。
func ToUpperSpecial(c unicode.SpecialCase, s string) string例
func TestLowerAndUpper(t *testing.T) {
fmt.Println(strings.ToLower("My name is jack,Nice to meet you!"))
fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "Önnek İş"))
fmt.Println(strings.ToUpper("My name is jack,Nice to meet you!"))
fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "örnek iş"))
}出力
=== RUN TestLowerAndUpper
my name is jack,nice to meet you!
önnek iş
MY NAME IS JACK,NICE TO MEET YOU!
ÖRNEK İŞ
--- PASS: TestLowerAndUpper (0.00s)
PASS文字列のトリム
文字列の両端をトリムし、cutset と一致する任意の部分文字列を削除します。
func Trim(s, cutset string) string文字列の左端をトリムし、cutset と一致する任意の部分文字列を削除します。
func TrimLeft(s, cutset string) string文字列の左端の接頭辞をトリムし、cutset と一致する部分文字列を削除します。一致しない場合は文字列 s を返します。
func TrimPrefix(s, suffix string) string文字列の右端をトリムし、cutset と一致する任意の部分文字列を削除します。
func TrimRight(s, cutset string) string文字列の右端の接尾辞をトリムし、cutset と一致する部分文字列を削除します。一致しない場合は文字列 s を返します。
func TrimSuffix(s, suffix string) string例
func TestTrim(t *testing.T) {
fmt.Println(strings.Trim("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimLeft("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimRight("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimPrefix("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimSuffix("!!this is a test statement!!", "!!!"))
}出力
=== RUN TestTrim
this is a test statement
this is a test statement!!
!!this is a test statement
!!this is a test statement!!
!!this is a test statement!!
--- PASS: TestTrim (0.00s)
PASS文字列 Builder
文字列 Builder は文字列を直接操作するよりもメモリを節約します。
type Builder struct {
// 内部フィールドは外部に公開されません
}例
func TestBuilder(t *testing.T) {
builder := strings.Builder{}
builder.WriteString("hello")
builder.WriteString(" world")
fmt.Println(builder.Len())
fmt.Println(builder.String())
}出力
=== RUN TestBuilder
11
hello world
--- PASS: TestBuilder (0.00s)
PASSTIP
Builder を値として渡さないでください。例えば、strings.Builder を関数パラメータとして渡す場合、プログラムは panic になります。
strings: illegal use of non-zero Builder copied by value内部には以下のようなコードがあります。
type Builder struct {
addr *Builder // 自身のアドレス
buf []byte
}
func (b *Builder) copyCheck() {
if b.addr == nil {
b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
} else if b.addr != b {
panic("strings: illegal use of non-zero Builder copied by value")
}
}Builder を値コピーする際、内部スライスのポインタもコピーされます。2 つの Builder は文字列を書き込む際に同じスライスに対して操作を行うため、値コピーが許可されていない理由です。
文字列 Replacer
Replacer は文字列の置換に使用されます。
func NewReplacer(oldnew ...string) *Replacer例
func TestReplacer(t *testing.T) {
r := strings.NewReplacer("<", "<", ">", ">")
fmt.Println(r.Replace("This is <b>HTML</b>!"))
}出力
This is <b>HTML</b>!文字列 Reader
Reader は io.Reader、io.ReaderAt、io.ByteReader、io.ByteScanner、io.RuneReader、io.RuneScanner、io.Seeker、および io.WriterTo インターフェースを実装します。
func NewReader(s string) *Reader例
func TestReader(t *testing.T) {
reader := strings.NewReader("abcdefghijk")
buffer := make([]byte, 20, 20)
read, err := reader.Read(buffer)
if err != nil {
log.Panic(err)
}
fmt.Println(read)
fmt.Println(string(buffer))
}出力
=== RUN TestReader
11
abcdefghijk
--- PASS: TestReader (0.00s)
PASS