文字列 #
文字列を宣言する #
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)
}
文字列を比較する #
文字列の比較には ==
を使った完全一致のほか、 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"))
}
文字列を連結する #
文字列同士は +
で連結できる。
package main
import (
"fmt"
)
func main() {
s1 := "hello"
s1 = s1 + " "
s1 += "world"
fmt.Println(s1)
}
文字列の配列を区切り文字指定で連結する #
文字列のスライスの要素同士は strings.Join
を使って連結できる。
package main
import (
"fmt"
"strings"
)
func main() {
list := []string{}
list = append(list, "hello")
list = append(list, "world")
fmt.Println(strings.Join(list, " "))
}
参考ドキュメント: 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())
}
参考ドキュメント: 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)
}
参考ドキュメント: 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)
}
}
参考ドキュメント: 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)
}
参考ドキュメント: 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
}
文字列の置換 #
単純な文字列同士の置換は 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"))
}
文字列を1文字づつ処理する #
package main
import (
"fmt"
)
func main() {
s := "hello world"
for i, v := range s {
fmt.Println(i, string(v))
}
}
マルチバイト文字列を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))
}
}
正規表現でマッチした文字列を処理する #
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])
}
}
参考ドキュメント: 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)
}
参考ドキュメント: math/rand