big.Int.MarshalText()
big.Int.MarshalText()
とは
big.Int.MarshalText()
は、Go言語のmath/big
パッケージで提供される多倍長整数型big.Int
のメソッドです。これは、encoding.TextMarshaler
インターフェースを実装しており、big.Int
の値をテキスト形式のバイトスライスとしてエンコード(シリアライズ)するために使用されます。
具体的には、big.Int
の値を10進数の文字列として表現し、それを[]byte
型で返します。例えば、big.NewInt(123456789)
というbig.Int
があれば、MarshalText()
は[]byte("123456789")
を返します。
インターフェースとしての役割
Go言語には、特定の形式にエンコード/デコードするための標準インターフェースがいくつかあります。encoding.TextMarshaler
はその一つで、以下のように定義されています。
type TextMarshaler interface {
MarshalText() (text []byte, err error)
}
big.Int
がこのインターフェースを実装しているということは、以下のような場面で特に便利です。
-
JSONエンコード/デコード
encoding/json
パッケージは、データ型がjson.Marshaler
またはencoding.TextMarshaler
を実装している場合、それを利用して自動的にJSON形式に変換します。これにより、big.Int
を直接JSONに含めることができ、その値は10進数の文字列として表現されます。import ( "encoding/json" "fmt" "math/big" ) type MyData struct { Value *big.Int `json:"value"` } func main() { num := big.NewInt(1234567890123456789) data := MyData{Value: num} jsonBytes, err := json.Marshal(data) if err != nil { fmt.Println(err) return } fmt.Println(string(jsonBytes)) // {"value":"1234567890123456789"} と出力される }
使用例
基本的な使用方法は以下の通りです。
package main
import (
"fmt"
"math/big"
)
func main() {
// big.Int のインスタンスを作成
num := new(big.Int)
num.SetString("98765432109876543210", 10) // 10進数で大きな数を設定
// MarshalText() を呼び出してテキスト形式のバイトスライスを取得
textBytes, err := num.MarshalText()
if err != nil {
fmt.Println("エラー:", err)
return
}
// バイトスライスを文字列に変換して表示
fmt.Println("テキスト形式:", string(textBytes)) // 出力: テキスト形式: 98765432109876543210
// nil の big.Int を MarshalText() した場合
var nilNum *big.Int
nilTextBytes, err := nilNum.MarshalText()
if err != nil {
fmt.Println("nilの場合のエラー:", err)
} else {
fmt.Println("nilの場合のテキスト形式:", string(nilTextBytes)) // 出力: nilの場合のテキスト形式: 0 (Go 1.15以降の挙動)
}
}
- Go 1.15以降では、nilの
*big.Int
に対してMarshalText()
を呼び出すと、"0"
を意味するバイトスライスが返されます。それ以前のバージョンでは、空のバイトスライスが返されることがありました。 - エラーは、基本的にメモリ不足などのシステムレベルの問題がない限り発生しません。
big.Int
の値が不正であるといった理由でエラーが返されることは通常ありません。 MarshalText()
はbig.Int
の値を10進数の文字列としてエンコードします。もし異なる基数(例:16進数)で表現したい場合は、big.Int.Text()
やbig.Int.String()
メソッドを使用し、適切な基数を指定する必要があります。
big.Int.MarshalText()
メソッド自体は非常にシンプルで、内部的にエラーを返すケースはごく稀です。しかし、その利用方法や連携するシステムとの間で問題が発生することがあります。
MarshalText()自体がエラーを返すケース (非常に稀)
- トラブルシューティング
- システムのリソース(メモリ)が不足していないか確認してください。
- 非常に巨大な
big.Int
の値を扱う場合、その文字列表現も非常に長大になり、それなりのメモリを消費します。もしOOMが疑われるなら、より効率的なストレージ方法を検討するか、処理を分割することを検討してください。
- エラーの状況
MarshalText()
メソッドが実際にエラーを返すのは、メモリ割り当ての失敗(OOM: Out Of Memory)など、システムレベルの深刻な問題が発生した場合に限られます。これはGoランタイムやOSの制約に起因するもので、アプリケーションのロジックエラーではありません。
nilの*big.IntをMarshalText()した場合の挙動の誤解
- トラブルシューティング
- Goのバージョンを確認し、そのバージョンの挙動を理解してください。
- もし、
nil
のbig.Int
が空文字列としてシリアライズされることを期待するなら、MarshalText()
を呼び出す前にnil
チェックを行い、手動で空のバイトスライスを返すロジックを実装してください。type MyData struct { Value *big.Int `json:"value"` } // カスタムのJSONマーシャリングを実装する例 func (md MyData) MarshalJSON() ([]byte, error) { if md.Value == nil { return []byte(`{"value":""}`), nil // もしくは `{"value":null}` } // 通常のMarshalText()に任せる return json.Marshal(struct { Value *big.Int `json:"value"` }{ Value: md.Value, }) }
- エラーの状況
Go 1.15より前のバージョンでは、nil
の*big.Int
に対してMarshalText()
を呼び出すと、空のバイトスライス([]byte{}
)が返されました。しかし、Go 1.15以降では、"0"
を表すバイトスライス([]byte("0")
)が返されるようになりました。この変更を知らないと、期待する出力と異なる場合があります。// Go 1.14 以前 var nilInt *big.Int text, _ := nilInt.MarshalText() fmt.Println(string(text)) // "" (空文字列) // Go 1.15 以降 var nilInt *big.Int text, _ := nilInt.MarshalText() fmt.Println(string(text)) // "0"
JSONエンコード/デコード時の問題
MarshalText()
が最も一般的に使われるのは、encoding/json
パッケージによるJSONエンコード時です。
-
トラブルシューティング
- 「数値として扱われることを期待したが文字列になった」
これはbig.Int
がencoding.TextMarshaler
を実装している仕様通りの挙動です。JSONの仕様上、大きな整数は通常文字列として扱うのがベストプラクティスです。もし数値として扱いたい場合は、カスタムマーシャラーを実装し、num.String()
ではなく、直接fmt.Sprintf("%s", num)
などでJSONに埋め込む必要がありますが、これは推奨されません。JSONデコーダによっては、非常に大きな数値を正しくパースできない可能性があります。 - 「デコード時にパースできない」
JSON文字列としてエンコードされたbig.Int
をデコードするには、big.Int
がencoding.TextUnmarshaler
を実装しているため、通常は問題ありません。しかし、JSON文字列が数値として扱われている場合、json.Unmarshal()
はエラーを返す可能性があります。// JSONが "value": 12345678901234567890 のように数値として来ている場合 // big.Int はこれを文字列としてしか期待しないため、エラーになる可能性がある // または、その数値がGoのint64の範囲内に収まらない場合、json.Unmarshalがエラーを返す
- 解決策
JSONを生成する側がbig.Int
を常に文字列として出力するように徹底してください(MarshalText()
の挙動がそれです)。デコードする側も文字列として受け取るようにしてください。
- 解決策
- 「クライアント側で丸められる」
これはGo側の問題ではなく、クライアント側の言語(JavaScriptなど)の数値型の制約によるものです。- 解決策
JSONを生成する際にbig.Int
を文字列として出力する (MarshalText()
のデフォルト挙動)。クライアント側でその文字列を受け取り、適切な多倍長整数ライブラリ(例: JavaScriptのBigInt
)を使用してパースしてください。これは、big.Int
を使用する最大の理由の一つでもあります。
- 解決策
- 「数値として扱われることを期待したが文字列になった」
-
big.Int
がJSON内で文字列としてではなく数値として扱われることを期待したが、実際には文字列としてエンコードされた。- JSONからデコードする際に、
big.Int
の値が正しくパースできない。 - JavaScriptなどのクライアント側で、非常に大きな整数が丸められてしまう(JavaScriptのNumber型は64ビット浮動小数点数で、正確に表現できる整数には限界があるため)。
異なる基数での表現
- トラブルシューティング
big.Int.Text(base int)
メソッドを使用してください。これにより、任意の基数で文字列表現を得ることができます。num := big.NewInt(255) hexText := num.Text(16) // "ff" fmt.Println(hexText) // もしJSONで特定の基数で出力したいなら、カスタムマーシャラーを実装する type MyHexData struct { Value *big.Int `json:"value"` } func (mhd MyHexData) MarshalJSON() ([]byte, error) { if mhd.Value == nil { return []byte("null"), nil } hexStr := fmt.Sprintf(`"%s"`, mhd.Value.Text(16)) // 16進数文字列をJSON文字列として囲む return []byte(hexStr), nil } data := MyHexData{Value: big.NewInt(255)} jsonBytes, _ := json.Marshal(data) fmt.Println(string(jsonBytes)) // "ff" とはならず、`{"value":"ff"}` のように出力される
- エラーの状況
MarshalText()
は常に10進数でエンコードします。もし16進数や別の基数でbig.Int
を表現したい場合、MarshalText()
は適切なメソッドではありません。
big.Int.MarshalText()
は主にencoding.TextMarshaler
インターフェースの実装として機能し、特にencoding/json
パッケージと組み合わせて使われることが多いです。ここでは、基本的な使い方から、JSONとの連携、nil値の扱いまで、具体的なコード例を挙げて説明します。
基本的なMarshalText()の使用
MarshalText()
は、big.Int
の値を10進数のバイトスライスとして返します。
package main
import (
"fmt"
"math/big"
)
func main() {
// 大きな整数を big.Int で定義
numStr := "1234567890123456789012345678901234567890"
num := new(big.Int)
num.SetString(numStr, 10) // 10進数で文字列をセット
fmt.Printf("元の big.Int の値: %s\n", num.String())
// MarshalText() を呼び出してバイトスライスを取得
textBytes, err := num.MarshalText()
if err != nil {
fmt.Printf("MarshalText() エラー: %v\n", err)
return
}
// バイトスライスを文字列に変換して表示
fmt.Printf("MarshalText() の結果 (string): %s\n", string(textBytes))
fmt.Printf("MarshalText() の結果 ([]byte): %v\n", textBytes)
// 非常に小さな値の場合
smallNum := big.NewInt(123)
smallTextBytes, err := smallNum.MarshalText()
if err != nil {
fmt.Printf("MarshalText() (小) エラー: %v\n", err)
return
}
fmt.Printf("MarshalText() (小) の結果: %s\n", string(smallTextBytes))
}
出力例
元の big.Int の値: 1234567890123456789012345678901234567890
MarshalText() の結果 (string): 1234567890123456789012345678901234567890
MarshalText() の結果 ([]byte): [49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48]
MarshalText() (小) の結果: 123
この例では、big.Int
の値がそのまま10進数の文字列としてバイトスライスに変換されることがわかります。
JSONエンコード/デコードでの使用
MarshalText()
の最も一般的なユースケースです。big.Int
がencoding.TextMarshaler
を実装しているため、json.Marshal
は自動的にMarshalText()
を呼び出し、big.Int
をJSON文字列としてエンコードします。
package main
import (
"encoding/json"
"fmt"
"math/big"
)
// JSONにエンコード/デコードしたい構造体
type Data struct {
ID int `json:"id"`
Value *big.Int `json:"value"` // big.Int はポインタ型で宣言するのが一般的
Price *big.Int `json:"price,omitempty"` // nilの場合はJSONに出力しない
}
func main() {
// 構造体のインスタンスを作成
num1 := new(big.Int)
num1.SetString("987654321098765432109876543210", 10)
data1 := Data{
ID: 1,
Value: num1,
Price: big.NewInt(500), // 値がある場合
}
// 構造体をJSONにエンコード
jsonData1, err := json.MarshalIndent(data1, "", " ") // 読みやすくするためにインデント付きで
if err != nil {
fmt.Printf("JSON Marshal エラー: %v\n", err)
return
}
fmt.Println("--- JSON エンコード例 ---")
fmt.Println(string(jsonData1))
// nilのbig.Intを含む構造体
data2 := Data{
ID: 2,
Value: big.NewInt(100), // 値がある場合
Price: nil, // nil の場合
}
jsonData2, err := json.MarshalIndent(data2, "", " ")
if err != nil {
fmt.Printf("JSON Marshal エラー: %v\n", err)
return
}
fmt.Println("\n--- nil の big.Int (Price) を含む JSON エンコード例 ---")
fmt.Println(string(jsonData2))
// 注意: Go 1.15以降では Value: nil の場合 "value":"0" となるが、omitemptyがあれば Price: nil は出力されない
// JSON文字列から構造体にデコード
fmt.Println("\n--- JSON デコード例 ---")
jsonStr := `{
"id": 3,
"value": "1122334455667788990011223344556677889900",
"price": "1000"
}`
var decodedData Data
err = json.Unmarshal([]byte(jsonStr), &decodedData)
if err != nil {
fmt.Printf("JSON Unmarshal エラー: %v\n", err)
return
}
fmt.Printf("デコードされた ID: %d\n", decodedData.ID)
fmt.Printf("デコードされた Value: %s (型: %T)\n", decodedData.Value.String(), decodedData.Value)
if decodedData.Price != nil {
fmt.Printf("デコードされた Price: %s (型: %T)\n", decodedData.Price.String(), decodedData.Price)
} else {
fmt.Println("デコードされた Price: nil")
}
// 値が0のケース (Go 1.15以降でMarshalText()が"0"を返す挙動)
fmt.Println("\n--- big.Int が 0 の場合の JSON エンコード ---")
dataZero := Data{ID: 4, Value: big.NewInt(0)}
jsonZero, err := json.MarshalIndent(dataZero, "", " ")
if err != nil {
fmt.Printf("JSON Marshal (Zero) エラー: %v\n", err)
return
}
fmt.Println(string(jsonZero)) // {"id": 4, "value": "0", "price": null} となる
}
出力例
--- JSON エンコード例 ---
{
"id": 1,
"value": "987654321098765432109876543210",
"price": "500"
}
--- nil の big.Int (Price) を含む JSON エンコード例 ---
{
"id": 2,
"value": "100"
}
--- JSON デコード例 ---
デコードされた ID: 3
デコードされた Value: 1122334455667788990011223344556677889900 (型: *math.Int)
デコードされた Price: 1000 (型: *math.Int)
--- big.Int が 0 の場合の JSON エンコード ---
{
"id": 4,
"value": "0"
}
この例から、big.Int
がJSONの文字列として自動的にシリアライズ・デシリアライズされることがわかります。これはMarshalText()
とUnmarshalText()
(big.Int
が実装)が提供する機能のおかげです。
nilの*big.IntとMarshalText()の挙動(Go 1.15以降)
Go 1.15以降、nil
の*big.Int
に対してMarshalText()
を呼び出すと"0"
を表すバイトスライスが返されます。この挙動は特にJSONのエンコードで影響します。
package main
import (
"encoding/json"
"fmt"
"math/big"
)
type NilTest struct {
MaybeValue *big.Int `json:"maybeValue"`
}
func main() {
fmt.Println("--- nil の *big.Int の MarshalText() 挙動 (Go 1.15以降) ---")
var nilBigInt *big.Int
text, err := nilBigInt.MarshalText()
if err != nil {
fmt.Printf("MarshalText() エラー: %v\n", err)
}
fmt.Printf("nilBigInt.MarshalText() の結果: %s\n", string(text)) // "0" が出力される
// JSONエンコードの場合
data := NilTest{MaybeValue: nil}
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
fmt.Printf("JSON Marshal エラー: %v\n", err)
return
}
fmt.Println("\n--- nil の *big.Int を含む JSON エンコード ---")
fmt.Println(string(jsonData)) // {"maybeValue": "0"} となる
}
出力例
--- nil の *big.Int の MarshalText() 挙動 (Go 1.15以降) ---
nilBigInt.MarshalText() の結果: 0
--- nil の *big.Int を含む JSON エンコード ---
{
"maybeValue": "0"
}
もしnil
の場合にJSONでnull
や空文字列を出力したい場合は、json:"omitempty"
タグを使うか、カスタムのMarshalJSON
メソッドを実装する必要があります。
カスタムのJSONマーシャリングでbig.Intのnilを制御する例
nil
のbig.Int
がJSONで"0"
として出力されるのを避けたい場合、カスタムのMarshalJSON
メソッドを実装できます。
package main
import (
"encoding/json"
"fmt"
"math/big"
)
type CustomData struct {
ID int `json:"id"`
Value *big.Int `json:"value"`
}
// CustomData の MarshalJSON メソッドを実装
func (cd CustomData) MarshalJSON() ([]byte, error) {
// 一時的な構造体を使って、big.Int の部分だけをカスタマイズ
type Alias CustomData // 無限ループを防ぐためのエイリアス
if cd.Value == nil {
// Value が nil の場合、null を出力する
// または空文字列 "" を出力したい場合は `fmt.Sprintf(`{"id":%d,"value":""}`, cd.ID)` など
return json.Marshal(&struct {
Alias
Value *string `json:"value"` // *string 型で null を表現
}{
Alias: Alias(cd),
Value: nil, // null を出力
})
}
// Value が nil でない場合は、デフォルトのマーシャリング挙動に任せる
// big.Int は MarshalText() を通じて文字列になる
return json.Marshal(Alias(cd))
}
func main() {
fmt.Println("--- カスタム MarshalJSON で nil の big.Int を制御 ---")
dataWithNil := CustomData{ID: 101, Value: nil}
jsonWithNil, err := json.MarshalIndent(dataWithNil, "", " ")
if err != nil {
fmt.Printf("JSON Marshal エラー: %v\n", err)
return
}
fmt.Println("Value が nil の場合:")
fmt.Println(string(jsonWithNil)) // {"id": 101, "value": null} となる
dataWithValue := CustomData{ID: 102, Value: big.NewInt(998877665544332211)}
jsonWithValue, err := json.MarshalIndent(dataWithValue, "", " ")
if err != nil {
fmt.Printf("JSON Marshal エラー: %v\n", err)
return
}
fmt.Println("\nValue が値を持つ場合:")
fmt.Println(string(jsonWithValue)) // {"id": 102, "value": "998877665544332211"} となる
}
--- カスタム MarshalJSON で nil の big.Int を制御 ---
Value が nil の場合:
{
"id": 101,
"value": null
}
Value が値を持つ場合:
{
"id": 102,
"value": "998877665544332211"
}
MarshalText()
はencoding.TextMarshaler
インターフェースの一部として、主にJSONなどのテキストベースのシリアライゼーションで自動的に呼び出されます。しかし、手動で文字列に変換したり、特定の形式で出力したりする場合には、別のメソッドを使います。
big.Int.String()
これは最も一般的でシンプルな代替方法です。big.Int
の値を10進数の文字列として返します。MarshalText()
が[]byte
を返すのに対し、String()
はstring
を返します。
特徴
fmt.Print()
やfmt.Sprintf()
などで%s
フォーマット動詞を使うと、内部的にこのString()
メソッドが呼び出されます。nil
の*big.Int
に対して呼び出すと、Go 1.15以降では"0"
を返します。(MarshalText()
と同じ挙動)- 最も直接的で、デバッグ出力などによく使われる。
- 常に10進数表現。
コード例
package main
import (
"fmt"
"math/big"
)
func main() {
num := new(big.Int)
num.SetString("12345678901234567890", 10)
// String() メソッドの使用
s := num.String()
fmt.Printf("String() の結果: %s (型: %T)\n", s, s)
// fmt.Sprintf() での利用 (内部で String() が呼ばれる)
formattedStr := fmt.Sprintf("フォーマットされた値: %s", num)
fmt.Println(formattedStr)
// nil の big.Int
var nilNum *big.Int
fmt.Printf("nil の String() 結果: %s\n", nilNum.String()) // "0" が出力される
}
出力例
String() の結果: 12345678901234567890 (型: string)
フォーマットされた値: 12345678901234567890
nil の String() 結果: 0
big.Int.Text(base int)
これは、指定された基数(base)でbig.Int
の値を文字列として表現したい場合に非常に便利です。例えば、16進数や2進数で出力したい場合に使います。
特徴
MarshalText()
が[]byte
を返すのに対し、Text()
はstring
を返す。- 結果は文字列として返される。
base
引数で基数を指定できる(2〜62)。
コード例
package main
import (
"fmt"
"math/big"
)
func main() {
num := big.NewInt(255) // 10進数の255
// 10進数で表示 (String() と同じ)
fmt.Printf("10進数: %s\n", num.Text(10))
// 16進数で表示
fmt.Printf("16進数: %s\n", num.Text(16)) // "ff"
// 2進数で表示
fmt.Printf("2進数: %s\n", num.Text(2)) // "11111111"
// 36進数で表示 (0-9a-z)
bigNum := new(big.Int)
bigNum.SetString("123456789012345678901234567890", 10)
fmt.Printf("36進数: %s\n", bigNum.Text(36))
}
出力例
10進数: 255
16進数: ff
2進数: 11111111
36進数: 6e9m7f8h9m7w4k9c2t7h0
big.Int.Append(buf []byte, base int)
既存のバイトスライスにbig.Int
の文字列表現を追記したい場合に効率的です。特に、大きな数を繰り返しエンコードする場合や、メモリ割り当てを最小限に抑えたい場合に有効です。
特徴
- メモリの再利用が可能になるため、パフォーマンスが向上する可能性がある。
- 既存の
[]byte
に追記し、新しい(または拡張された)[]byte
を返す。 base
引数で基数を指定できる。
コード例
package main
import (
"fmt"
"math/big"
)
func main() {
num := big.NewInt(123456)
// 空のバイトスライスに追記
buf := make([]byte, 0, 32) // 容量を事前に確保
buf = num.Append(buf, 10)
fmt.Printf("Append(10進数): %s (長さ: %d, 容量: %d)\n", string(buf), len(buf), cap(buf))
// 別のバイトスライスに追記
anotherBuf := []byte("Prefix: ")
anotherBuf = num.Append(anotherBuf, 16) // 16進数で追記
fmt.Printf("Append(16進数、プレフィックスあり): %s\n", string(anotherBuf))
}
出力例
Append(10進数): 123456 (長さ: 6, 容量: 32)
Append(16進数、プレフィックスあり): Prefix: 1e240
カスタムのMarshalJSON() / UnmarshalJSON() メソッド
MarshalText()
はencoding.TextMarshaler
を介してJSONと連携しますが、JSON出力の形式をより細かく制御したい場合(例:nil値をnull
として出力したい、特定のフィールドを数値として扱いたいなど)は、json.Marshaler
およびjson.Unmarshaler
インターフェースを直接実装します。
特徴
json
パッケージによる自動変換をバイパスする。big.Int
のデフォルトのMarshalText()
/UnmarshalText()
の挙動を上書きできる。- JSONへの変換ロジックを完全にカスタマイズできる。
コード例
package main
import (
"encoding/json"
"fmt"
"math/big"
)
type MyCustomInt struct {
Value *big.Int `json:"value"`
}
// MarshalJSON は MyCustomInt のJSONエンコードをカスタマイズします。
func (mci MyCustomInt) MarshalJSON() ([]byte, error) {
if mci.Value == nil {
return []byte("null"), nil // nil の場合は JSON null を出力
}
// big.Int を文字列として出力する (MarshalText() と同じ結果をJSON文字列として返す)
return []byte(fmt.Sprintf(`"%s"`, mci.Value.String())), nil
}
// UnmarshalJSON は MyCustomInt のJSONデコードをカスタマイズします。
func (mci *MyCustomInt) UnmarshalJSON(data []byte) error {
s := string(data)
if s == "null" {
mci.Value = nil
return nil
}
// JSON文字列から big.Int をパース
// JSONの "..." 部分を削除する必要がある場合がある
// 例: `"123"` の " を削除
if len(s) > 1 && s[0] == '"' && s[len(s)-1] == '"' {
s = s[1 : len(s)-1]
}
num := new(big.Int)
_, ok := num.SetString(s, 10)
if !ok {
return fmt.Errorf("無効な big.Int 文字列: %s", s)
}
mci.Value = num
return nil
}
func main() {
fmt.Println("--- カスタム MarshalJSON/UnmarshalJSON の例 ---")
// nil の値のエンコード
data1 := MyCustomInt{Value: nil}
json1, _ := json.MarshalIndent(data1, "", " ")
fmt.Printf("nil の MarshalJSON: %s\n", string(json1))
// 値がある場合のエンコード
data2 := MyCustomInt{Value: big.NewInt(1234567890)}
json2, _ := json.MarshalIndent(data2, "", " ")
fmt.Printf("値がある場合の MarshalJSON: %s\n", string(json2))
// nil 値のデコード
jsonStr1 := `{"id":1,"value":null}`
var decoded1 MyCustomInt
err := json.Unmarshal([]byte(jsonStr1), &decoded1)
if err != nil {
fmt.Printf("Unmarshal エラー (null): %v\n", err)
} else {
fmt.Printf("Unmarshal (null) 結果: %v\n", decoded1.Value)
}
// 値がある場合のデコード
jsonStr2 := `{"id":2,"value":"987654321"}`
var decoded2 MyCustomInt
err = json.Unmarshal([]byte(jsonStr2), &decoded2)
if err != nil {
fmt.Printf("Unmarshal エラー (値あり): %v\n", err)
} else {
fmt.Printf("Unmarshal (値あり) 結果: %s\n", decoded2.Value.String())
}
}
出力例
--- カスタム MarshalJSON/UnmarshalJSON の例 ---
nil の MarshalJSON: {
"value": null
}
値がある場合の MarshalJSON: {
"value": "1234567890"
}
Unmarshal (null) 結果: <nil>
Unmarshal (値あり) 結果: 987654321
big.Int.MarshalText()
はbig.Int
を10進数のテキスト形式のバイトスライスに変換する標準的な方法であり、特にencoding/json
パッケージと組み合わせる場合に自動的に機能します。しかし、より柔軟な出力形式(異なる基数)、既存のバッファへの追記、またはJSON出力の特定の挙動(nil値の扱いなど)を詳細に制御したい場合は、String()
、Text()
、Append()
、またはカスタムのMarshalJSON()
/ UnmarshalJSON()
メソッドが代替手段として有効です。