避免这种情况/避免这种情况发生的一种简单且常见的方法是
type使用关键字创建一个新类型,并使用类型转换来传递该类型的值(该值可能是您的原始值,因为新的类型具有原始类型作为其基础类型)。
之所以
type可行,是因为关键字创建了一个新类型,并且该新类型将具有零个方法(它不会“继承”基础类型的方法)。
这会产生一些运行时开销吗?编号。从规格报价:转换:
特定规则适用于数字类型之间或字符串类型之间的(非恒定)转换。这些转换可能会更改的表示形式
x并产生运行时成本。
所有其他转换只会更改类型,而不会更改的表示形式x。
让我们来看一个例子。我们有一个
Person带有数字的类型
Age,我们要确保
Age不能为负数(小于
0)。
type Person struct { Name string `json:"name"` Age int `json:"age"`}func (p *Person) UnmarshalJSON(data []byte) error { type person2 Person if err := json.Unmarshal(data, (*person2)(p)); err != nil { return err } // Post-processing after unmarshaling: if p.Age < 0 { p.Age = 0 } return nil}测试它:
var p *Personfmt.Println(json.Unmarshal([]byte(`{"name":"Bob","age":10}`), &p))fmt.Println(p)fmt.Println(json.Unmarshal([]byte(`{"name":"Bob","age":-1}`), &p))fmt.Println(p)输出(在Go Playground上尝试):
<nil>&{Bob 10}<nil>&{Bob 0}当然,相同的技术也适用于自定义封送处理(
MarshalJSON()):
func (p *Person) MarshalJSON() ([]byte, error) { // Pre-processing before marshaling: if p.Age < 0 { p.Age = 0 } type person2 Person return json.Marshal((*person2)(p))}测试它:
p = &Person{"Bob", 10}fmt.Println(json.NewEnprer(os.Stdout).Enpre(p))p = &Person{"Bob", -1}fmt.Println(json.NewEnprer(os.Stdout).Enpre(p))输出(在相同的Go Playground示例中):
{"name":"Bob","age":10}<nil>{"name":"Bob","age":0}<nil>一个非常相似的问题是,当您
String()string为
fmt包定义自定义文本表示方法时,您想使用所修改的默认字符串表示形式。



