Golang实践录:反射reflect的一些研究及代码汇总
Posted 李迟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang实践录:反射reflect的一些研究及代码汇总相关的知识,希望对你有一定的参考价值。
本文汇总一些工程中使用到的和 reflect 有关的代码示例。由于是代码片段,不一定保证完整。
解析json
本节介绍解析json的一些方法。json 可来自文件,也可来自字符串,无论哪种,都是先转换成[]byte
,再调用json.Unmarshal
解析。
有时候并不关注完整的 json 格式,我们可以只取其中一部分字段,因此,可使用map[string]interface{}
来接收解析结果(注意如是数组,则须使用数组形式)。
从json文件解析其字段
file, err := os.Open(filename)
if err != nil {
fmt.Printf("open file %s error: %s\\n", filename, err)
return
}
defer file.Close()
read := io.Reader(file)
data, _ := ioutil.ReadAll(read)
var v []map[string]interface{}
err = json.Unmarshal(data, &v)
if err != nil {
fmt.Printf("Unmarshal error: %s\\n", err)
return
}
// 假定filename里面有很多的json数组,一一遍历
for _, idx := range v {
fmt.Println(idx["foo"])
...
}
从json字符串解析
一个简单的示例,从字符串组装,到解析,到提取其中某个字段。
func TestJsonSimple(t *testing.T) {
// 原始json字符串不能格式化,必须转换成[]byte
orgJsonString :=
`{"enID":"ID250","exID":"ID251","type":1,"money":250.44,"distance":274050}`
// 虽然不知道具体结构体,但知道json只有一个,不是数组
var data map[string]interface{}
// 解析
err := json.Unmarshal([]byte(orgJsonString), &data)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("%#v\\n", data);
fmt.Println(data["money"]) // 并不关心其它字段,只抽取所需的
fmt.Println(data["money1"]) // 不存在,返回nil
}
输出:
map[string]interface {}{"distance":274050, "enID":"ID250", "exID":"ID251", "money":250.44, "type":1}
250.44
<nil>
json中嵌套数组,并获取数组内容:
func showInterface(origin interface{}) {
switch reflect.TypeOf(origin).Kind() {
case reflect.Slice, reflect.Array:
s := reflect.ValueOf(origin)
for i := 0; i < s.Len(); i++ {
fmt.Printf("%d: %v\\n", i, s.Index(i))
}
case reflect.String:
s := reflect.ValueOf(origin)
fmt.Printf("only string %v\\n", s.String())
case reflect.Int:
s := reflect.ValueOf(origin)
fmt.Printf("only int %v\\n", s.Int())
}
}
func TestJsonArray(t *testing.T) {
orgJsonString :=
`{"enID":"ID500","exID":"ID501","type":2,"money":27.00,"distance":28322,"splitInfo":[{"index":1,"pTag":"11","pMoney":700},{"index":2,"pTag":"12","pMoney":2000}]}`
// 解析
var data map[string]interface{}
err := json.Unmarshal([]byte(orgJsonString), &data)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("org json:\\n%#v\\n\\n", data);
showInterface(data["enID"])
showInterface(data["splitInfo"])
}
data["splitInfo"]
是一个interface
,此刻并不知道具体的内容,因此无法再获取内部的字段或长度。可以利用reflect.TypeOf
获取类型,如是数组,需要遍历。详见代码。
输出:
org json:
map[string]interface {}{"distance":28322, "enID":"ID500", "exID":"ID501", "money":27, "splitInfo":[]interface {}{map[string]interface {}{"index":1, "pMoney":700, "pTag":"11"}, map[string]interface {}{"index":2, "pMoney":2000, "pTag":"12"}}, "type":2}
only string ID500
0: map[index:1 pMoney:700 pTag:11]
1: map[index:2 pMoney:2000 pTag:12]
接上,如果只需要获取data["splitInfo"]
的长度。注意,此处是知道该字段是数组,但不知道其内容(或不关注内容),可直接用reflect.ValueOf
求出长度,如下:
mylen := reflect.ValueOf(data["splitInfo"]).Len()
fmt.Println("splitInfo len: ", mylen)
以上是关于Golang实践录:反射reflect的一些研究及代码汇总的主要内容,如果未能解决你的问题,请参考以下文章