为了与大摇大摆进行交互,我需要制作一个自定义BigInt结构,该结构只不过是围绕go’s进行包装big.Int。
BigInt
big.Int
type BigInt struct { big.Int } ... type SpendTx struct { SenderID string `json:"sender_id,omitempty"` RecipientID string `json:"recipient_id,omitempty"` Amount utils.BigInt `json:"amount,omitempty"` Fee utils.BigInt `json:"fee,omitempty"` Payload string `json:"payload,omitempty"` TTL uint64 `json:"ttl,omitempty"` Nonce uint64 `json:"nonce,omitempty"` } func (t SpendTx) JSON() (output []byte, err error) { return json.Marshal(t) }
我希望SpendTx.JSON()最终会打来电话big.Int.MarshalJSON(),会回来0。相反,我得到了以下输出:
SpendTx.JSON()
big.Int.MarshalJSON()
0
{"sender_id":"alice","recipient_id":"bob","amount":{},"fee":{},"payload":"Hello World","ttl":10,"nonce":1}
但是我真正想要的是:
{"sender_id":"alice","recipient_id":"bob","amount":10,"fee":10,"payload":"Hello World","ttl":10,"nonce":1}
而且我必须添加以下代码BigInt来做到这一点:
func (b BigInt) MarshalJSON() ([]byte, error) { return b.Int.MarshalJSON() }
但是,根据Effective Go的关于嵌入结构的部分,这根本没有必要。为什么big.Int显示为{}?
{}
big.Int实现自定义JSON marshaler(json.Marshaler),请参见Int.MarshalJSON()。但是此方法具有指针接收器,因此只有在具有指针值:时,才使用/调用该方法*big.Int。
json.Marshaler
Int.MarshalJSON()
*big.Int
并且您嵌入了一个非指针值,因此不会调用此自定义封送拆收器,并且由于big.Int它是具有未导出字段的结构,因此您将在输出中看到一个空的JSON对象:{}。
为了使其工作,您应该使用指向您的类型的指针,例如:
Amount *utils.BigInt `json:"amount,omitempty"` Fee *utils.BigInt `json:"fee,omitempty"`
使用它的示例:
s := SpendTx{ SenderID: "alice", RecipientID: "bob", Amount: &utils.BigInt{}, Fee: &utils.BigInt{}, } data, err := s.JSON() fmt.Println(string(data), err)
然后以输出为例(在Go Playground上尝试):
{"sender_id":"alice","recipient_id":"bob","amount":0,"fee":0} <nil>
另一个选择是使用non-pointer utils.BigInt,但是utils.BigInt应该嵌入一个指针类型:
utils.BigInt
type BigInt struct { *big.Int } type SpendTx struct { Amount utils.BigInt `json:"amount,omitempty"` Fee utils.BigInt `json:"fee,omitempty"` }
然后使用它:
s := SpendTx{ SenderID: "alice", RecipientID: "bob", Amount: utils.BigInt{new(big.Int)}, Fee: utils.BigInt{new(big.Int)}, } data, err := s.JSON() fmt.Println(string(data), err)
再次输出(在Go Playground上尝试):