[Golang] String(文字列)

2021-10-28 hit count image

GolangでString(文字列)を宣言して使う方法に説明します。

概要

今回のブログポストではGolangでString(文字列)を使って変数を生成して使う方法について説明します。このブログポストで紹介するコードは次のリンクで確認できます。

文字列

Golangでは次のように文字列を宣言して使うことができます。

str1 := "Hello\nWorld!"
fmt.Println(str1)

また、次のように\`を使って複数行の文字列を宣言して使うことができます。

str2 := `Hello
World!`
fmt.Println(str2)

これを確認するとためmain.goファイルを生成して次のように修正します。

package main

import "fmt"

func main() {
  str1 := "Hello\nWorld!"
  fmt.Println(str1)

  str2 := `Hello
World!`
  fmt.Println(str2)
}

これを実行すると次のような結果が表示されます。

# go run main.go
Hello
World!
Hello
World!

文字列の巡回

Golangでは次のように文字列を巡回することができます。

str1 := "Hello, world!"

for i := 0; i < len(str1); i++ {
  fmt.Printf("%c", str1[i])
}

しかし、len()はバイトの長さをリターンします。したがって、韓国語のような1バイトではない文字を使うと文字がうまく表示されません。(韓国語>3バイト)

str2 := "Hello, 월드!"

for i := 0; i < len(str2); i++ {
  fmt.Printf("%c", str2[i])
}

この時rune(int32タイプのエイリアス)タイプを使って、文字1つを4バイトに変換して、出力する必要があります。

str3 := "Hello, 월드!"
arr := []rune(str3)

for i := 0; i < len(arr); i++ {
  fmt.Printf("%c", arr[i])
}

これを確認するためmain.goファイルを次のように修正します。

package main

import "fmt"

func main() {
  str1 := "Hello, world!"

  for i := 0; i < len(str1); i++ {
    fmt.Printf("%c", str1[i])
  }

  fmt.Println()

  str2 := "Hello, 월드!"

  for i := 0; i < len(str2); i++ {
    fmt.Printf("%c", str2[i])
  }

  fmt.Println()

  str3 := "Hello, 월드!"
  arr := []rune(str3)

  for i := 0; i < len(arr); i++ {
    fmt.Printf("%c", arr[i])
  }
}

これを実行すると次のような結果が表示されます。

# go run main.go
Hello, world!
Hello, ìë!
Hello, 월드!%

文字列の演算

Golangでは文字列を使って次のような演算を使うことができます。

文字列の加算

Golangでは+演算子を使って次のように文字列を加算することができます。

package main

import "fmt"

func main() {
  str1 := "Hello"
  str2 := "world!"
  fmt.Println(str1 + " " + str2)

  str := "Hello"
  str += " " + "world!"
  fmt.Println(str)
}

これを確認するためmain.goファイルを修正して実行すると、次のような結果が表示されます。

# go run main.go
Hello world!
Hello world!

比較演算

Golangでは次のように比較演算子を使って文字列を比較することができます。

package main

import "fmt"

func main() {
  str3 := "a"
  str4 := "b"
  fmt.Println(str3 == str4)
  fmt.Println(str3 != str4)
  fmt.Println(str3 < str4)
  fmt.Println(str3 > str4)
}

文字のサイズを比較する時には当該文字のコードの値を使って比較することになります。

  • A-Z: 65-90
  • a-z: 97-122

これを確認するため、main.goファイルを修正して実行すると、次のような結果が表示されます。

# go run main.go
false
true
true
false

文字列はポインタ

Golangでは基本的同じサイズのデータだけ変数に割り当てることができます。しかし、文字列はデータによって文字列の長さが変わり、データのサイズが変わります。しかし、文字列はGolangの基本ルールを破ってデータを割り当てられています。その理由は文字列はポインタなのであります。

これを確認するため、main.goファイルを次のように修正します。

package main

import (
  "fmt"
  "reflect"
  "unsafe"
)

func main() {
  str1 := "Hello, World!"
  str2 := str1

  strHeader1 := (*reflect.StringHeader)(unsafe.Pointer(&str1))
  strHeader2 := (*reflect.StringHeader)(unsafe.Pointer(&str2))

  fmt.Println(strHeader1)
  fmt.Println(strHeader2)
}

これを実行すると次のような結果が表示されます。

&{17444156 13}
&{17444156 13}

結果を確認すると、同じメモリアドレスを持って、同じサイズのデータが保存されてることが確認できます。

文字列は不変です

文字列は基本的不変(Immutable)の値です。

package main

import "fmt"

func main() {
  str := "Hello, World!"
  str = "Hello"
  fmt.Println(str)

  // str[0] = "a" // ERROR
}

したがって、全部を再割り当てることはできますが、1つの文字だけ変更することはできません。

もし、1つの文字だけを変更したい場合は次のように文字列を新いslice変数に割り当てた後修正すれば良いです。

package main

import "fmt"

func main() {
  var str1 string = "Hello, World!"
  var slice []byte = []byte(str1)

  slice[0] = "h"[0]
  fmt.Println(str1)
  fmt.Printf("%s\n", slice)
}

これを実行すると次のような結果が表示されます。

# go run main.go
Hello, World!
hello, World!

strings パッケージ

Golangでは文字列を扱う時、Golangで提供するstringsパッケージを使います。

stringsパッケージは色んな機能を効率的実装したので、自ら実装するより性能が良いです。したがって、文字列を扱うプログラムを作る場合は、上のリンクでstringsパッケージが提供する機能を先に確認した方が良いです。

package main

import (
  "fmt"
  "strings"
)

func main() {
  str := "hello, world!"
  fmt.Println(strings.ToUpper(str))
  fmt.Println(strings.Contains(str, "hello"))
  fmt.Println(strings.Index(str, "w"))
  fmt.Println(strings.Compare("a", "b"))
}

上の内容を実行すると下記のような結果が表示されます。

# go run main.go
HELLO, WORLD!
true
7
-1

完了

これでGolangで文字列を生成して使う方法についてみてみました。また、Golangで文字列の特上を見て、Golangが基本的提供するstringsパッケージを使って文字列を扱う方法もみてみました。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

Posts