json - Golang 中的类型转换

标签 json pointers go syntax type-conversion

我正在阅读以下文章:
https://www.ribice.ba/golang-enums/

在其中一个代码示例中定义了一个函数:

func (lt *LeaveType) UnmarshalJSON(b []byte) error {
    // Define a secondary type to avoid ending up with a recursive call to json.Unmarshal
    type LT LeaveType;
    var r *LT = (*LT)(lt);
    err := json.Unmarshal(b, &r)
    if err != nil{
        panic(err)
    }
    switch *lt {
    case AnnualLeave, Sick, BankHoliday, Other:
        return nil
    }
    return errors.New("Inalid leave type")
}
var r *LT = (*LT)(lt); 的语法是什么在这个例子中做什么?

最佳答案

从技术上讲,Go 没有强制转换,而是转换。显式转换的语法是 T(x)在哪里 T是某种类型和x是可转换为该类型的某个值。见 Conversions in the Go specification详情。

从函数的声明中可以看出:

func (lt *LeaveType) UnmarshalJSON(b []byte) error {

lt本身具有指向 LeaveType 的类型指针和 UnmarshalJSON*LeaveType 类型的接收器函数. encoding/json当包要设置的变量的类型为 LeaveType 时,包将调用这样的函数来解码输入 JSON (或 *LeaveType — 在这种情况下,包将自行创建 LeaveType 变量)。

正如代码中的注释所说,代码的作者现在想要 encoding/json代码解码 JSON,就好像没有函数 UnmarshalJSON .但是有一个功能UnmarshalJSON ,所以如果我们只调用 encoding/json没有一点技巧的代码,encoding/json只会再次调用这个函数,导致无限递归。

通过定义新类型 LT其内容与现有类型 LeaveType 完全相同,我们最终得到了一个没有接收函数的新类型。调用 encoding/json在这种类型的实例(或指向这种类型的指针)上不会调用 *LeaveType接收者,因为 LT是一个不同的类型,即使它的内容完全匹配。

我们可以这样做:
func (lt *LeaveType) UnmarshalJSON(b []byte) error {
    type LT LeaveType
    var r LT
    err := json.Unmarshal(b, &r)
    if err != nil {
        panic(err)
    }
    // ...
}

这将填写 r ,其大小和形状与任何 LeaveType 相同多变的。那么我们就可以使用填入的r设置*lt :
*lt = LeaveType(r) // an ordinary conversion

之后我们可以像以前一样继续使用 *lt作为值(value)。但这意味着 UnmarshalJSON必须设置一个临时变量 r ,然后我们必须将其复制到其最终目的地。为什么不设置一些东西,以便 UnmarshalJSON填写目标变量,但是使用我们选择的类型?

这就是这里的语法。这不是最短的版本:正如 Cerise Limón 所指出的,有一种更短的拼写方式(通常首选更短的拼写方式)。 (*LT)(lt) 中的第一组括号需要绑定(bind) * ——指向部分的指针——指向 LT ,如 *LT(lt)绑定(bind)错误:与 *(LT(lt)) 含义相同这不是我们想要的。

关于json - Golang 中的类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60440743/

相关文章:

c++ - 是否可以使用旧版 C++ 中的 C++ 库?

java - 从大型 txt 文件中删除非 UTF-8 字符

c - pthreads create_pthread() 传递多个参数

c++ - 使用指针时的奇怪行为

go - 当只读来自 HTTP 处理程序的共享结构时如何防止竞争条件

go - 从 Golang 中的字符串中 slice 特定部分

json - Swift Codable 期望解码 Dictionary<String, Any> 但发现了一个字符串/数据

javascript - 如何从一堆计算值中逐个分配 Vue 对象的属性?

c# - 如何在 C# 中声明 C++ 指针

sorting - 如何使用默认排序函数对golang中的整数数组进行排序