LoginSignup
1
0

More than 1 year has passed since last update.

【Golang】数値をコンマ区切りで出力する【1000桁単位のカンマ区切りフォーマット出力】

Last updated at Posted at 2022-10-08

Go 言語(以下 Golang)で int(1000) ---> "1,000"コンマ区切りでフォーマット出力したい。

しかし、fmt パッケージには専用の関数がなさげ。どうしよう。

独自実装やサードパーティのパッケージを使わずに、golang.org 管轄下のパッケージでフォーマットできないものか

「golang コンマ区切り カンマ区切り 出力 フォーマット」でググるも、独自実装だったり、コンマ区切りの入力を処理するものばかりだったので自分のググラビリティとして。

TL; DR (今北産業)

  1. Go の準標準モジュール golang.org/x/textmessage パッケージで可能。

    • message は、ロケールに合わせたテキスト整形ツール郡で fmt の代替パッケージです。
  2. 桁の区切りカンマやピリオドは国によって記法が異なる。message で調整が可能。

  3. マスター、動くものをくれ。

    package main
    
    import (
    	"golang.org/x/text/language"
    	"golang.org/x/text/message"
    )
    
    func main() {
    	value := 1000
    
    	p := message.NewPrinter(language.Japanese)
    
    	p.Printf("%d\n", value)
    
    	// Output: 1,000
    }
    
    ロケールによる表記の違い
    package main
    
    import (
    	"golang.org/x/text/language"
    	"golang.org/x/text/message"
    	"golang.org/x/text/number"
    )
    
    func main() {
    	value := 1234567.89
    
    	for _, langTag := range []language.Tag{
    		language.English,
    		language.Japanese,
    		language.French,
    	} {
    		p := message.NewPrinter(langTag)
    
    		p.Println(langTag)
    		p.Printf("  Message: %f\n", value)
    		p.Printf("  Number : %v\n", number.Decimal(value))
    	}
    
    	// Output:
    	// en
    	//   Message: 1,234,567.890000
    	//   Number : 1,234,567.89
    	// ja
    	//   Message: 1,234,567.890000
    	//   Number : 1,234,567.89
    	// fr
    	//   Message: 1 234 567,890000
    	//   Number : 1 234 567,89
    }
    

TS; DR

1000桁区切りにコンマは国によって異なる

小数点や桁の区切りは、国によって記法が異なることをご存じでしょうか。

例えば、日本では 1234567.89 という値は 1,234,567.89 とも記載できますが、1.234.567,89 だったり 12,34,567.891 234 567,891'234'567,89 という、日本とは異なる記法の国もあるのです。

日本でも「百二十三万四千五百六十七点八九」という記法もある事を考えればわかる気もします。

他にも、日付の 2001 年 10 月 11 日を 01/10/11 という YMD 記法の国もあれは、11/10/01DMY)だったり 10/11/01MDY)という国もあります。

つまり、国によって数値の記法が異なるということです。

表記のローカライズ

そこで、「その国に合わせた記述方法」に変換することを「ローカライズlocalize」(地域化)と言います。

OS で「ロケールlocale」を変更すると、数値や日付の表記が変わるのを経験したことはないでしょうか。アレです。

ゆうて、筆者も「なぜ標準で数値のフォーマッターがないんだ。PHP なら number_format があるのに」と思い調べていたところ、number モジュールがフォーマッターであることはわかったものの、messagePrinter オブジェクトを通して処理しています。

なぜそんな七面倒臭いことをするのだろうと思って message のドキュメントを読んでいたら「ロケールの問題か!」と気付かされたのです。

message から以下の抜粋を翻訳してみました。

Localized Formatting

A format string can be localized by replacing any of the print functions of fmt with an equivalent call to a Printer.

p := message.NewPrinter(message.MatchLanguage("en"))
p.Println(123456.78) // Prints 123,456.78

p.Printf("%d ducks in a row", 4331) // Prints 4,331 ducks in a row

p := message.NewPrinter(message.MatchLanguage("nl"))
p.Printf("Hoogte: %.1f meter", 1244.9) // Prints Hoogte: 1,244.9 meter

p := message.NewPrinter(message.MatchLanguage("bn"))
p.Println(123456.78) // Prints ১,২৩,৪৫৬.৭৮

Printer currently supports numbers and specialized types for which packages exist in x/text. Other builtin types such as time.Time and slices are planned.

Format strings largely have the same meaning as with fmt with the following notable exceptions:

  • flag # always resorts to fmt for printing
  • verb 'f', 'e', 'g', 'd' use localized formatting unless the '#' flag is specified.
  • verb 'm' inserts a translation of a string argument.

See package fmt for more options.

Localized Formatting | message @ pkg.go.dev より)

▼ 以下筆者翻訳

ローカライズされたフォーマットによる文字列整形

文字列のフォーマット(整形)は、fmtPrint 系の関数に相当するmessage.Printer オブジェクトのメソッドに置き換えることでローカライズ(地域化)することができます。

p := message.NewPrinter(message.MatchLanguage("en"))
p.Println(123456.78) // 出力: "123,456.78"

p.Printf("%d ducks in a row", 4331) // 出力: "4,331 ducks in a row"

p := message.NewPrinter(message.MatchLanguage("nl"))
p.Printf("Hoogte: %.1f meter", 1244.9) // 出力: "Hoogte: 1,244.9 meter"

p := message.NewPrinter(message.MatchLanguage("bn"))
p.Println(123456.78) // 出力: "১,২৩,৪৫৬.৭৮"

現在、message.Printer 型は、数字と x/text パッケージに存在する特殊な型のみをサポートしています。その他の time.Time やスライスなどのビルトインの型は、今後実装が予定されています。

文字列のフォーマットは、以下の顕著な例外を除いて、 fmt とほぼ同じ意味を持っています

  • # フラグは常に fmt を使用します。
  • verb 'f', 'e', 'g', 'd' use localized formatting unless the '#' flag is specified.
  • "%d" などの f, e, g, d 動詞は、# フラグが指定されない限り、地域化された書式を使用します。
  • m 動詞は、引数の文字列の翻訳を挿入します。(※)

その他のオプションについては fmt パッケージのドキュメントをご覧ください。

※ 【筆者注】 message には国際化のための翻訳辞書機能があるようです。しかし、ドキュメントのサンプルが動かないため、使い方もよくわかりません。分かり次第追記か別記事にしたいと思います。

参考文献

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