GoLang学习(三)

本章节主要是Json编码/解码,golang里面的json编码/解码比python还简单,运行环境内置了json函数库,不需要单独安装模块;另外,可以支持自定义struct编解码和Java中的类似,可以把json转换成有类似属性的某个类。有一点需要注意,结构体中如果包含结构体,最好别用指针,否则用起来比较麻烦。

1、非指针方式,以下代码运行和预期一样

//导入模块
import(
        "fmt"
        "encoding/json"
      )
//定义两个数据结构
type Item struct{
    SName string
    IValue int
}
type JObject struct{
    IValue int
    SValue string
    SArray []string
    IArray[] int
    SIMap map[string]int
    OArray []Item
    SOMap map[string]Item
}
//编解码函数
func testEncoding(){
    var obj JObject
        obj.IValue=1
        obj.SValue="this is string"
        obj.IArray=[]int{1,2,3,4,5,5}
        obj.SArray=make([]string,10)
        obj.SIMap=make(map[string]int)
        obj.SIMap["akey"]=1
        obj.SIMap["bkey"]=2
        var item1 Item
            item1.SName="item name"
            item1.IValue=1
        obj.OArray=make([]Item,10)
        obj.OArray[0]=item1
        obj.SOMap=make(map[string]Item)
        obj.SOMap["abc"]=item1
    buf,err :=json.Marshal(&obj)
    if err==nil{
        fmt.Printf("encoding : %s\n",string(buf))
    }else{
        fmt.Printf("encoding error : %s\n",err.Error())
    }
}
func testDecoding(){
    var jsonstring=`{"IValue":1,"SValue":"this is string","SArray":["","","","","","","","","",""],"IArray":[1,2,3,4,5,5],"SIMap":{"akey":1,"bkey":2},"OArray":[{"SName":"item name","IValue":1},null,null,null,null,null,null,null,null,null],"SOMap":{"abc":{"SName":"item name","IValue":1}}}`
    var obj JObject
    err :=json.Unmarshal([]byte(jsonstring),&obj)
    if err==nil{
        fmt.Printf("json decode result : %#v\n",obj)
    }else{
        fmt.Printf("encoding error : %s\n",err.Error())
    }
}
//main函数
func main(){
    testEncoding()
    testDecoding()
}

2、把结构体JObject里面的某个属性修改成指针类型;

type JObject struct{
    IValue int
    SValue string
    SArray []string
    IArray[] int
    SIMap map[string]int
    OArray []*Item   //此处修改成指针数组
    SOMap map[string]Item
}
//编码解码函数需要做相应的调整
func testEncoding(){
    var obj JObject
        obj.IValue=1
        obj.SValue="this is string"
        obj.IArray=[]int{1,2,3,4,5,5}
        obj.SArray=make([]string,10)
        obj.SIMap=make(map[string]int)
        obj.SIMap["akey"]=1
        obj.SIMap["bkey"]=2
        var item1 Item
            item1.SName="item name"
            item1.IValue=1
        obj.OArray=make([]*Item,10)  //此处修改为指针类型
        obj.OArray[0]=&item1  //此处
        obj.SOMap=make(map[string]Item)
        obj.SOMap["abc"]=item1
    buf,err :=json.Marshal(&obj)
    if err==nil{
        fmt.Printf("encoding : %s\n",string(buf))
    }else{
        fmt.Printf("encoding error : %s\n",err.Error())
    }
}
 
//解码函数
func testDecoding(){
    var jsonstring=`{"IValue":1,"SValue":"this is string","SArray":["","","","","","","","","",""],"IArray":[1,2,3,4,5,5],"SIMap":{"akey":1,"bkey":2},"OArray":[{"SName":"item name","IValue":1},null,null,null,null,null,null,null,null,null],"SOMap":{"abc":{"SName":"item name","IValue":1}}}`
    var obj JObject
        obj.OArray=make([]*Item,10) //A:此处初始化一个数组
        var item1 Item
        obj.OArray[0]=&item1 //B:此处引用
    err :=json.Unmarshal([]byte(jsonstring),&obj)
    if err==nil{
        fmt.Printf("item1 : %#v\n",item1)
        fmt.Printf("json decode result : %#v\n",obj)
    }else{
        fmt.Printf("encoding error : %s\n",err.Error())
    }
}

编码运行结果:通第一个例子
解码运行结果:

item1 : main.Item{SName:"item name", IValue:1}
json decode result : main.JObject{IValue:1, SValue:"this is string", SArray:[]string{"", "", "", "", "", "", "", "", "", ""}, IArray:[]int{1, 2, 3, 4, 5, 5}, SIMap:map[string]int{"akey":1, "bkey":2}, OArray:[]*main.Item{(*main.Item)(0x21021d200), (*main.Item)(nil), (*main.Item)(nil), (*main.Item)(nil), (*main.Item)(nil), (*main.Item)(nil), (*main.Item)(nil), (*main.Item)(nil), (*main.Item)(nil), (*main.Item)(nil)}, SOMap:map[string]main.Item{"abc":main.Item{SName:"item name", IValue:1}}}

数组第一个元素是非空的,因为预先给这个指针引用了一个数据,如果在解码函数中去掉A到B三行,解码出来的数组都会是(nil)。
这就引发一个问题,一般我们不知道数组的长度是多少,也就是A处无法写长度,那么就无法正确解码出来了,得到的都是(nil)。
看decode.go代码的实现,没有对指针的处理,也就是遇到指针的情况没有处理。仔细想是对的,解码函数内部不应该[分配内存]返回一个指针,这个恰恰是调用者应该做的。

所以,如果不用指针用起来会更方便。

————–EOF————–

分享到: 更多