Golang中如何解析JSON数据
Golang中如何解析JSON数据
我正在尝试理解 interface{} 和 &interface{} 之间的区别。我搞不清楚为什么在第一个代码片段中,反序列化是在 Map 数据类型中完成的,而在第二个片段中,反序列化是在 struct 数据类型中完成的。
案例 1:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
}
func Decode(p interface{}) {
str := `
{"name" : "aryan"}
`
json.Unmarshal([]byte(str), &p)
fmt.Printf("%+v \n", p)
}
func main() {
p := Person{}
Decode(p)
fmt.Printf("%+v \n", p)
}
输出
map[name:aryan]
{Name:}
案例 2:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
}
func Decode(p interface{}) {
str := `
{"name" : "aryan"}
`
json.Unmarshal([]byte(str), &p)
fmt.Printf("%+v \n", p)
}
func main() {
p := &Person{}
Decode(p)
fmt.Printf("%+v \n", p)
}
输出
&{Name:aryan}
&{Name:aryan}
我对案例 1、3 和 4 很清楚。但在这里的案例 2 中,我们将地址传递给了接口值,然后在反序列化时再次传递了该指针的地址。那么,反序列化是如何处理指向指针的指针的呢?
案例 3:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
}
func Decode(p interface{}) {
str := `
{"name" : "aryan"}
`
json.Unmarshal([]byte(str), p)
fmt.Printf("%+v \n", p)
}
func main() {
p := &Person{}
Decode(p)
fmt.Printf("%+v \n", p)
}
输出
&{Name:aryan}
&{Name:aryan}
案例 4:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
}
func Decode(p interface{}) {
str := `
{"name" : "aryan"}
`
json.Unmarshal([]byte(str), p)
fmt.Printf("%+v \n", p)
}
func main() {
p := Person{}
Decode(p)
fmt.Printf("%+v \n", p)
}
输出
{Name:}
{Name:}
更多关于Golang中如何解析JSON数据的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你好 @aryanmaurya1,
Decode() 函数的参数是一个接口类型,但在调用 Decode(p) 时,实际参数 p 是一个指向 Person 的指针。
你可以在 Decode() 内部打印 p 的类型来确认这一点:
json.Unmarshal([]byte(str), &p)
fmt.Printf("%T \n", p) // T 代表 "type"
输出:
*main.Person
更多关于Golang中如何解析JSON数据的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在案例2中,json.Unmarshal([]byte(str), &p) 确实传递了指向接口值的指针,这形成了双重指针。让我们分析具体的工作原理:
func main() {
p := &Person{} // p 是 *Person 类型
Decode(p) // p 作为 interface{} 传递
}
func Decode(p interface{}) {
// 此时 p 是一个接口值,包含:
// - 类型: *Person
// - 值: 指向 Person 结构体的指针
// &p 获取的是接口变量本身的地址
// 这相当于 **Person(指向指针的指针)
json.Unmarshal([]byte(str), &p)
}
json.Unmarshal 能够正确处理这种情况,因为当它接收到 &p(接口变量的地址)时:
- 类型检查:
Unmarshal检查发现参数是*interface{}类型 - 解引用:它会解引用一次,得到
interface{}值 - 反射处理:通过反射发现接口值中存储的是
*Person类型 - 最终目标:继续解引用,将数据写入实际的
Person结构体
验证示例:
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Person struct {
Name string `json:"name"`
}
func Decode(p interface{}) {
str := `{"name" : "aryan"}`
fmt.Printf("p 的类型: %v\n", reflect.TypeOf(p))
fmt.Printf("&p 的类型: %v\n", reflect.TypeOf(&p))
json.Unmarshal([]byte(str), &p)
fmt.Printf("Decode 内部: %+v\n", p)
}
func main() {
p := &Person{}
fmt.Printf("main 中 p 的类型: %T\n", p)
Decode(p)
fmt.Printf("main 中 p 的值: %+v\n", p)
}
输出:
main 中 p 的类型: *main.Person
p 的类型: *main.Person
&p 的类型: *interface {}
Decode 内部: &{Name:aryan}
main 中 p 的值: &{Name:aryan}
关键点:
json.Unmarshal的第二个参数必须是目标值的指针- 当传递
&p时,Unmarshal通过反射能够正确处理多重指针 - 最终数据会正确写入原始的
Person结构体
这种设计允许 Unmarshal 处理各种复杂情况,包括接口类型和多重指针。

