1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Golang-文字数を数える方法,4バイト以上の絵文字もある

Posted at

背景

こちらの記事 UTF-8 のテーブル(MySQL5.6)に竈門禰󠄀豆子が格納できない問題を調べてみたがきっかけで、
Golangにおける絵文字の文字数を確認する方法を調査して見ました。

ちなみに、Golang のソースコードや文字列リテラルは UTF-8 が採用されています。
UTF-8 は、英数字は 8bit で表現して、それ以外は 16,24,32bit で可変的に表現しています。
例えば、ひらがなカタカナ漢字の様な日本語は 2 byte のものが多いのですが、上記の記事にでもあった一部の異体字(wikipedia)は 4 byte だったりします。

あと、😺 とかの絵文字も 4byte のものが多いのですが、
🧑‍🤝‍🧑 や 👨‍👩‍👧‍👦 といった絵文字は複数の絵文字を組み合わせた絵文字で、 4byte 以上になったりします。

確認用コード

Go version: go1.17.8

package main

import (
	"fmt"
	"runtime"
	"unicode/utf8"

	"github.com/rivo/uniseg"
)

func main() {
	fmt.Printf("Go version: %s\n", runtime.Version())
	emoji := "😺"

	// 文字数
	println(1 == utf8.RuneCountInString(emoji))

	// バイト数
	println(4 == len(emoji))

	// バイト数(😺 ) = 4bytes
	println(4 == utf8.RuneLen('😺')) // RuneLen は,文字のエンコードに必要なバイト数を返します。
	println(1 == utf8.RuneLen('a'))

	emoji2 := "🧑‍🤝‍🧑"
	println(5 == utf8.RuneCountInString(emoji2)) // 文字数(🧑‍🤝‍🧑 ) = 5 . (4bytesを超えた文字はutf8.RuneLen関数を使用できない)
	println(18 == len(emoji2))                   // バイト数(🧑‍🤝‍🧑 ) = 18bytes

	// uniseg という Go 言語用パッケージがあって,これを使うと UTF-8 文字列を「文字」単位に切り出してくれる。
	gr := uniseg.NewGraphemes(emoji2)
	for gr.Next() {
		rs := gr.Runes()
		fmt.Printf("%v : %U\n", string(rs), rs)
	}
	// Output: 🧑‍🤝‍🧑 : [U+1F9D1 U+200D U+1F91D U+200D U+1F9D1]

	// おまけ:string以外に []byte と []rune の文字数とバイト数も求め方も
	buf := []byte("😺")
	runes := []rune("😺")

	println(1 == utf8.RuneCount(buf))
	println(1 == len(runes))

	println(4 == len(buf))
	println(4 == len(string(runes)))
}

Golang Playground Demo

元記事

Golang-文字数を数える方法,4バイト以上の絵文字もある

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?