文字列

文字列 #

文字列を宣言する #

package main

import (
	"fmt"
)

func main() {
	// 文字列リテラル
	s1 := "hello world"
	fmt.Println(s1)

	// 複数行の文字列
	s2 := `
hello
multi
line
`
	fmt.Println(s2)

	// 既存の文字列の部分文字列を取得
	s3 := s1[:5]
	fmt.Println(s3)
}
play_circleRun open_in_newRun In The Playground

文字列を比較する #

文字列の比較には == を使った完全一致のほか、 strings パッケージを使った部分一致・前方一致・後方一致や regexp パッケージを使ったパターンとの一致などの検査がある。

package main

import (
	"fmt"
	"regexp"
	"strings"
)

func main() {
	// 完全一致の検査
	fmt.Println(1, "hello" == "hello")

	// 部分一致の検査
	fmt.Println(2, strings.Contains("hello world", ""))
	fmt.Println(3, strings.Contains("hello world", "hello"))
	fmt.Println(4, strings.Contains("hello world", "world"))
	fmt.Println(5, strings.Contains("hello world", "not found"))

	// 前方一致の検査
	fmt.Println(6, strings.HasPrefix("hello world", "hello"))
	fmt.Println(7, strings.HasPrefix("hello world", "world"))

	// 後方一致の検査
	fmt.Println(8, strings.HasSuffix("hello world", "hello"))
	fmt.Println(9, strings.HasSuffix("hello world", "world"))

	// 正規表現による検査
	matched, err := regexp.MatchString(`^h`, "hello world")
	fmt.Println(10, matched, err)
	matched, err = regexp.MatchString(`^Hello`, "hello world")
	fmt.Println(11, matched, err)

	// 正規表現による検査(正規表現をコンパイルして使い回す場合)
	r, err := regexp.Compile(`\s+world`)
	if err != nil {
		panic(err)
	}
	fmt.Println(12, r.MatchString("hello world"))
	fmt.Println(13, r.MatchString("Hello World"))
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: strings , regexp

文字列を連結する #

文字列同士は + で連結できる。

package main

import (
	"fmt"
)

func main() {
	s1 := "hello"
	s1 = s1 + " "
	s1 += "world"
	fmt.Println(s1)
}
play_circleRun open_in_newRun In The Playground

文字列の配列を区切り文字指定で連結する #

文字列のスライスの要素同士は strings.Join を使って連結できる。

package main

import (
	"fmt"
	"strings"
)

func main() {
	list := []string{}
	list = append(list, "hello")
	list = append(list, "world")
	fmt.Println(strings.Join(list, " "))
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: strings

効率的に文字列を連結する #

bytes.Buffer を使って文字列を連結すると + で連結する場合などに比べて処理効率が良くなる。

package main

import (
	"bytes"
	"fmt"
)

func main() {
	var b bytes.Buffer
	b.Write([]byte("hello "))
	b.WriteString(" new")
	fmt.Fprintf(&b, " world")
	fmt.Println(b.String())
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: bytes

文字列を分割する #

文字列を分割する場合、文字列を文字の配列として扱い部分配列を取得する方法や strings.Split を使う方法などがある。

package main

import (
	"fmt"
	"strings"
)

func main() {
	s := "hello world"

	// インデックス指定で分割する
	s1, s2 := s[:5], s[5:]
	fmt.Printf("s1:\"%s\", s2:\"%s\"\n", s1, s2)

	// 区切り文字で分割する
	list := strings.Split(s, " ")
	fmt.Printf("%#v\n", list)
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: strings

文章を行単位で処理する #

複数行の文字列を改行文字で分割することで行単位で処理することができる。

package main

import (
	"fmt"
	"strings"
)

func main() {
	lines := `line1
line2
line3
line4
line5`

	for i, line := range strings.Split(lines, "\n") {
		fmt.Printf("[%d] %s\n", i, line)
	}
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: strings

文字列から数値への変換 #

文字列から数値への変換には strconv パッケージを利用する。

package main

import (
	"fmt"
	"strconv"
)

func main() {
	// string から int
	i, err := strconv.Atoi("-42")
	fmt.Println(i, err)

	// string から bool
	b, err := strconv.ParseBool("true")
	fmt.Println(b, err)

	// string から float64
	f, err := strconv.ParseFloat("3.1415", 64)
	fmt.Println(f, err)

	// string から int64
	i64, err := strconv.ParseInt("-42", 10, 64)
	fmt.Println(i64, err)

	// string から uint
	u, err := strconv.ParseUint("42", 10, 64)
	fmt.Println(u, err)
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: strconv

数値から文字列への変換 #

数値から文字列への変換は fmt.Sprint などの fmt パッケージを使うと各数値の型に合わせて適切な文字列へ変換してくれる。 また strconv の変換用の関数を使うとフォーマットを細かく制御できる。

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var s string

	// bool から string
	s = fmt.Sprint(true)
	fmt.Println(s) // == true

	// int から string
	s = fmt.Sprint(int(100))
	fmt.Println(s) // == 100

	// int64 から string
	s = fmt.Sprint(int64(-42))
	fmt.Println(s) // == -42

	// uint から string
	s = fmt.Sprint(uint(6400))
	fmt.Println(s) // == 6400

	// float64 から string
	s = fmt.Sprint(3.1415)
	fmt.Println(s) // == 3.1415

	// bool から string
	fmt.Println(strconv.FormatBool(true)) // == true

	// int64 から string
	fmt.Println(strconv.FormatInt(-42, 10)) // == -42

	// uint から string
	fmt.Println(strconv.FormatUint(42, 10)) // 42

	// int64 から 8 進数表記の string
	fmt.Println(strconv.FormatInt(-42, 8)) // -52

	// int64 から 16 進数表記の string
	fmt.Println(strconv.FormatInt(-42, 16)) // -2a

	// float64 から string
	fmt.Println(strconv.FormatFloat(3.1415, 'E', -1, 64)) // == 3.1415E+00
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: fmt , strconv

文字列の置換 #

単純な文字列同士の置換は strings.ReplaceAll を使い、パターンによる置換は regexp を使う。

package main

import (
	"fmt"
	"log"
	"regexp"
	"strings"
)

func main() {
	// 固定文字列の置換
	fmt.Println(strings.ReplaceAll("hello world", "l", "L"))
	fmt.Println(strings.ReplaceAll("hello world", "hello", "Hello"))

	// 正規表現でマッチした文字列の置換
	r, err := regexp.Compile(`\s+world`)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(r.ReplaceAllString("hello world", " World"))
	fmt.Println(r.ReplaceAllString("hello    world", " World"))
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: strings , regexp

文字列を1文字づつ処理する #

package main

import (
	"fmt"
)

func main() {
	s := "hello world"

	for i, v := range s {
		fmt.Println(i, string(v))
	}
}
play_circleRun open_in_newRun In The Playground

マルチバイト文字列を1文字づつ処理する #

string[]rune に変換するとマルチバイトの文字単位で扱える。

package main

import (
	"fmt"
)

func main() {
	s := "こんにちは世界"
	r := []rune(s)

	fmt.Printf("string:%d, []rune:%d\n", len(s), len(r))

	for i, v := range r {
		fmt.Println(i, v, string(v))
	}
}
play_circleRun open_in_newRun In The Playground

正規表現でマッチした文字列を処理する #

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// マッチした文字列をすべて処理する
	re1 := regexp.MustCompile(`\S+`)
	matched1 := re1.FindAllString("hello new world !", -1)
	for i, m := range matched1 {
		fmt.Printf("[%d]%s\n", i, m)
	}

	// マッチした文字列とサブマッチした文字列をすべて処理する
	re2 := regexp.MustCompile(`(\S)\S+(\S)`)
	matched2 := re2.FindAllStringSubmatch("hello new world !", -1)
	for i, m := range matched2 {
		fmt.Printf("[%d]match:%s, head:%s, tail:%s\n", i, m[0], m[1], m[2])
	}

}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: regexp

ランダムな文字列を生成する #

package main

import (
	"fmt"
	"math/rand"
)

const characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func main() {
	fmt.Println(RandomString(8))
	fmt.Println(RandomString(16))
}

func RandomString(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = characters[rand.Intn(len(characters))]
	}
	return string(b)
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: math/rand