Skip to content

strings

strings パッケージは UTF-8 エンコードされた文字列を操作するシンプルな関数を実装します。簡単に言えば、文字列操作のためのユーティリティパッケージです。

公式ドキュメント:strings package - strings - Go Packages

TIP

Go はネイティブで UTF8 文字をサポートしており、すべての文字列操作は UTF8 に基づいて構築されています。

インポート

go
import (
   "strings"
)

以下では例を使用して一般的な関数を説明します。

文字列の複製

go
func Clone(s string) string

複製されたコピー用に新しいメモリを割り当てます。空の文字列を渡した場合、メモリは割り当てられず、空の文字列が返されます。

go
func TestClone(t *testing.T) {
   ori := "hello 世界"
   copys := strings.Clone(ori)
   fmt.Println(ori, copys)
   fmt.Println(&ori, &copys)
}
=== RUN   TestClone
hello 世界 hello 世界
0xc00005e5d0 0xc00005e5e0
--- PASS: TestClone (0.00s)
PASS

文字列の比較

go
func Compare(a, b string) int

a と b を辞書順で文字列比較します。a>b の場合 1 を返し、a<b の場合 -1 を返し、a=b の場合 0 を返します。

go
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

文字列の包含

go
func Contains(s, substr string) bool

文字列 s が部分文字列 substr を含んでいるかどうかを判断します。

go
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)
PASS
go
func ContainsAny(s, chars string) bool

文字列 chars 内の任意の文字の Unicode コードが文字列 s 内にあるかどうかを判断します。つまり、s が chars 内の任意の文字列を含んでいるかどうかを判断します。

go
func TestContainsAny(t *testing.T) {
  fmt.Println(strings.ContainsAny("abcedfg", "bac"))
  fmt.Println(strings.ContainsAny("abcedfg", "gfdecba"))
}
=== RUN   TestContainsAny
true
--- PASS: TestContainsAny (0.00s)
PASS
go
func ContainsRune(s string, r rune) bool

文字列 s が文字 r を含んでいるかどうかを判断します。

go
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

部分文字列の出現回数

go
func Count(s, substr string) int

部分文字列 substr が文字列 s 内に出現する回数を返します。

go
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

指定された部分文字列の削除

go
func Cut(s, sep string) (before, after string, found bool)

s 内で最初に出現する部分文字列 sep を削除し、削除後の結果を返します。

  • before - 削除された部分文字列の前の文字列
  • after - 削除された部分文字列の後の文字列
  • found - 部分文字列が見つかったかどうか
go
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

大文字小文字を無視した等価比較

go
func EqualFold(s, t string) bool

文字列 s と t が大文字小文字を無視して等しいかどうかを返します。

go
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

文字列の分割

go
func Fields(s string) []string
go
func FieldsFunc(s string, f func(rune) bool) []string

前者はスペースに基づいて文字列を分割し、後者は関数 f の戻り値に基づいて文字列を分割するかどうかを決定します。

go
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

接頭辞・接尾辞の検索

go
func HasPrefix(s, prefix string) bool
go
func HasSuffix(s, suffix string) bool

前者は接頭辞を検索し、後者は接尾辞を検索します。興味がある方はソースコードの実装をご覧ください。巧妙な実装です。

go
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

部分文字列の位置

最初に出現する部分文字列のインデックスを返します。

go
func Index(s, substr string) int

最初に出現する部分文字列のインデックスを返します。

go
func IndexAny(s, chars string) int

最初に出現する部分文字列のインデックスを返します。

go
func IndexRune(s string, r rune) int

go
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

最後に出現する部分文字列のインデックスを返します。

go
func LastIndex(s, substr string) int

最後に出現する部分文字列の任意の文字のインデックスを返します。

go
func LastIndexAny(s, chars string) int

go
func TestLastIndex(t *testing.T) {
  fmt.Println(strings.LastIndex("abcdefga", "a"))
  fmt.Println(strings.LastIndexAny("abcdefghisa", "ba"))
}

文字列の走査・置換

Map は文字列 s のコピーを返し、マッピング関数に基づいて文字列 s のすべての文字を変更します。マップが負の値を返す場合、その文字は文字列から削除され、置換されません。

go
func Map(mapping func(rune) rune, s string) string

go
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"))
}

出力

text
=== RUN   TestMap
ABCDEFGHIJK
abcdefghijk
FGHIJK
--- PASS: TestMap (0.00s)
PASS

文字列の複製

指定された Count に基づいて文字列を複製します。負の数の場合、panic になります。

go
func Repeat(s string, count int) string

go
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 未満の場合、置換回数は制限されません。

go
func Replace(s, old, new string, n int) string

go
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)
PASS

Replace のユーティリティ関数で、stings.Replace(s,old,new,-1) と等価です。

go
func ReplaceAll(s, old, new string) string

go
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 を文字列スライスに分割します。

go
func Split(s, sep string) []string

部分文字列 sep に基づいて文字列 s を文字列スライスに分割します。分割回数は n によって決定されます。

go
func SplitN(s, sep string, n int) []string

部分文字列 sep に基づいて文字列 s を sep を含む文字列要素で構成された文字列スライスに分割します。

go
func SplitAfter(s, sep string) []string

部分文字列 sep に基づいて文字列 s を sep を含む文字列要素で構成された文字列スライスに分割します。分割回数は n によって決定されます。

go
func SplitAfterN(s, sep string, n int) []string

go
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

大文字小文字の変換

英字文字列を小文字に変換します。

go
func ToLower(s string) string

対応する言語の unicode.SpecialCase に基づいて、対応する言語の小文字に変換します。

go
func ToLowerSpecial(c unicode.SpecialCase, s string) string

英字文字列を大文字に変換します。

go
func ToUpper(s string) string

対応する言語の unicode.SpecialCase に基づいて、対応する言語の大文字に変換します。

go
func ToUpperSpecial(c unicode.SpecialCase, s string) string

go
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 と一致する任意の部分文字列を削除します。

go
func Trim(s, cutset string) string

文字列の左端をトリムし、cutset と一致する任意の部分文字列を削除します。

go
func TrimLeft(s, cutset string) string

文字列の左端の接頭辞をトリムし、cutset と一致する部分文字列を削除します。一致しない場合は文字列 s を返します。

go
func TrimPrefix(s, suffix string) string

文字列の右端をトリムし、cutset と一致する任意の部分文字列を削除します。

go
func TrimRight(s, cutset string) string

文字列の右端の接尾辞をトリムし、cutset と一致する部分文字列を削除します。一致しない場合は文字列 s を返します。

go
func TrimSuffix(s, suffix string) string

go
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 は文字列を直接操作するよりもメモリを節約します。

go
type Builder struct {
  // 内部フィールドは外部に公開されません
}

go
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)
PASS

TIP

Builder を値として渡さないでください。例えば、strings.Builder を関数パラメータとして渡す場合、プログラムは panic になります。

strings: illegal use of non-zero Builder copied by value

内部には以下のようなコードがあります。

go
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 は文字列の置換に使用されます。

go
func NewReplacer(oldnew ...string) *Replacer

go
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 インターフェースを実装します。

go
func NewReader(s string) *Reader

go
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

Golang学习网由www.golangdev.cn整理维护