我在Golang中正确使用重命名的类型吗?

时间:2019-03-01 15:31:54

标签: go

我必须处理来自Swagger定义的REST API的Golang中的巨大整数。由于Swagger需要一个Validate(strfmt.Registry),因此我可以这样定义我的自定义类型:

// BigInt is a big.Int, but includes a Validate() method for swagger
// Once created, it can be used just like a big.Int.
type BigInt struct {
    *big.Int
}

由于需要与JSON进行转换,因此我定义了一些JSON Marshaling接口:

// UnmarshalJSON implements encoding/json/RawMessage.UnmarshalJSON
func (b *BigInt) UnmarshalJSON(data []byte) error {
    err := json.Unmarshal(data, &b.Int)
    if err != nil {
        return err
    }

    return nil
}

// MarshalJSON calls json.Marshal() on the BigInt.Int field.
func (b *BigInt) MarshalJSON() ([]byte, error) {
    if b == nil {
        return []byte("null"), nil
    }
    return json.Marshal(b.Int)
}

现在,我意识到我的自定义类型实际上并不完全像big.Int。为了比较两个BigInts:

example := BigInt{Int: &big.Int{}}
other := BigInt{Int: &big.Int{}}
example.Cmp(other.Int)

我做不到

example.Cmp(other)

这更干净。创建BigInt也是一种糟糕的体验,我必须将其包装成这样的函数:

// NewBigInt creates a BigInt with its Int struct field 
func NewBigInt() (i *BigInt) {
    return &BigInt{Int: &big.Int{}}
}
  1. 这真的是我应该做的事情吗?
  2. 为什么golang不能把big.Int像其他内置类型int64/uint64/float64一样对待?

1 个答案:

答案 0 :(得分:2)

  

这真的是我应该做的事情吗?

这是一种的实现方式,但这不是我所说的“重命名”类型;这是一个包含单个字段的结构。您也可以这样做(例如,time.Duration):

type BigInt *big.Int

并对其应用方法。这样一来,您就可以在*big.Int和您的类型之间进行无缝转换。

  

为什么golang无法将big.Int像其他内置类型(如int64 / uint64 / float64)一样对待?

由于与那些类型不同,big.Int不是内置类型;您可以知道,因为它是big.Int,也就是说,它是在包中定义的,而不是在语言中定义的。