go结构体总结(+Json 高级进阶) + 接口

1.结构体和Json, 成员变量名必须要大写字母开头,否则解析失败

go中根据首字母的大小写来确定可以访问的权限。无论是方法名、常量、变量名还是结构体的名称,如果首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用

type CurrUser struct{
    Name      string  `json:"name,omitempty"`  //如果为空值,则转json的时候,该字段不生成,从没有该字段的json字符串转结构体的时候,不报错,为默认值
    No        int     `json:"no,omitempty"`
    Uniqueid  string  `json:"uniqueid,omitempty"`
}

结构体中的成员变量是byte切片的时候,生成的json会自动进行base64编码,解析的时候,反过来也同理

type MrEventDataMessage struct {	
	Body   []byte       `json:"body,omitempty"`
}
mrEventMessage := MrEventDataMessage{Body:[]byte("xiaoyu你好!")}
str, _ := json.Marshal(&mrEventMessage)
log.Error("BagItemSub MrEventMessage  %s", string(str))
decodeBytes, _ := base64.StdEncoding.DecodeString("eGlhb3l15L2g5aW977yB")
fmt.Println(string(decodeBytes))

结构体只要包含json字符串中部分需要解析的成员就可以了,不需要使用的字段可以不写在结构体的成员变量中

 

结构体中嵌套的结构体,可以是指针

type InStr struct {
	Age int64 `json:"age,omitempty"`
}

type TestStruct struct {
	Name  string `json:"name,omitempty"`
	ID    int32  `json:"id,omitempty"`
	MyAge *InStr `json:"myage,omitempty"`
	No    *int64 `json:"no,omitempty"`
}

inStr := InStr{Age: 20}
	iNo := int64(110)
	testStruct := TestStruct{Name: "xiaoyu",
		ID:    16,
		MyAge: &inStr,
		No:    &iNo}
	fmt.Println(testStruct)
	byteJson, _ := json.Marshal(testStruct)
	fmt.Println(string(byteJson))

生成嵌套json:
{"name":"xiaoyu","id":16,"myage":{"age":20},"no":110}

 

结构体成员如果是枚举类型,最终生成的json值也是 数值类型,比如赋值TeamType_DISCUZ,实际值为1

type TeamType int32

const (
	TeamType_GROUP    TeamType = 0
	TeamType_DISCUZ   TeamType = 1
	TeamType_CHATROOM TeamType = 2
)

type Team struct {
	Id       string            `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
	Name     string            `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
	HeadImg  string            `protobuf:"bytes,3,opt,name=head_img,json=headImg" json:"head_img,omitempty"`
	Type     TeamType          `protobuf:"varint,4,opt,name=type,enum=com.sencent.im.model.TeamType" json:"type,omitempty"`
	Silenced bool              `protobuf:"varint,5,opt,name=silenced" json:"silenced,omitempty"`
	
}
team := &Team{Id : "123", Type : TeamType_DISCUZ}
byteJson, _ := json.Marshal(team)
strJson := string(byteJson)  

"{"id":"123","type":1}"

结构体中嵌套不确定结构的结构体,使用接口就行了:

type Group struct {	
	Name     string            `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
	HeadImg  string            `protobuf:"bytes,3,opt,name=head_img,json=headImg" json:"head_img,omitempty"`	
}
type Msg struct {	
	Info     string            `protobuf:"bytes,2,opt,name=info" json:"info,omitempty"`
}

type ApiRsp struct{
	ErrCode int64  `protobuf:"bytes,1,opt,name=err_code" json:"err_code,omitempty"`
	Data  interface{}    `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`  
	Msg  interface{}    `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"` 
}

func main(){
	group := Group{Name:"xiaoyu"}
	msg := Msg{Info : "i don't konw"}
	apiRsp := &ApiRsp{ErrCode : 1, Data : &group, Msg :&msg}
	byteJson, _ := json.Marshal(apiRsp)
	strJson := string(byteJson)  
	fmt.Println(strJson)
}

2.利用反射获得结构体的成员变量名

package main

import (
    "fmt"
    "reflect"
)

type User struct{
    UName string
}

type resume struct {
    Name string //`json:"name" doc:"我的名字"`
    Sex  string //`json:"name" doc:"我的名字"`
    Age  int
    Tel  string
    SUser User
}

//注意stru是接口,传递参数的时候是结构体指针
func findDoc(stru interface{}) map[string]string {
    t := reflect.TypeOf(stru).Elem()
    doc := make(map[string]string)

    for i := 0; i < t.NumField(); i++ {
        //doc[t.Field(i).Tag.Get("json")] = t.Field(i).Tag.Get("doc")
        fmt.Println(t.Field(i).Name)
    }

    return doc

}

func main() {
    stru := resume{}
    doc := findDoc(&stru)
    fmt.Printf("name字段为:%s\n", doc["name"])
}

2.接口

iValue := 100 //默认是int类型,要赋值给int32 /int64要进行类型转换

package main
import "fmt" 
func main() {
    var a interface{} //没有赋值(类型,实现任何接口)是nil类型
//a.(string) 会崩溃,空接口转其他类型会崩溃,使用ok进行判断
	//var b string
	//a = "asdasdasdasd"
	//a = 32 int类型, 不同于int32/int64,不能直接转换
	a = int32(32) //int64类型
	switch a.(type){
	case string:
		fmt.Print("string\n")
	case int:
		fmt.Print("int\n")
	case int32:
		fmt.Print("int32\n")
	case int64:
		fmt.Print("int64\n")
	case nil:
		fmt.Print("nil\n")		
	}
	if c, ok := a.(int32); ok{
		fmt.Println(c)
	}
	value := a.(int64)  //类型不对,会crash
	fmt.Println(value)
}
 



运用案例:

解析的时候,要将Data 转为具体的对象数组(切片),不然解析不到对象,注意要使用&arrAccount指针

type ApiRsp struct{
	ErrCode int64  			`protobuf:"bytes,1,opt,name=error_code" json:"error_code"`
	//如果Data为nil,则生成的json中Data的值为null,不雅观,所以赋值一个大小为0的切片 
	Data    interface{}   	`protobuf:"bytes,1,opt,name=data" json:"data"`  //, omitempty
	Msg     string    	    `protobuf:"bytes,1,opt,name=message" json:"message"` 
}

func (apiRsp *ApiRsp)GetJsonString() string{
	strJson, _ := json.Marshal(apiRsp)
	return string(strJson)	
}

//data必须是数组,切片,对象指针或者nil,能够自动将obj转为[]
//{"err_code":0,"data":[数组],"msg":""}
func ApiHttpRsp(c *gin.Context, errCode int64, data interface{}, msg string ){
	empData := make([]interface{}, 0) //避免Data :[NULL]	
	apiRsp := &ApiRsp{ErrCode : 0, Data : empData, Msg : ""}
	apiRsp.ErrCode = errCode
	apiRsp.Msg = msg
	if (nil != data){
		strType := reflect.TypeOf(data).Kind() //如果data是nil,.Kind()方法会报错
		if (reflect.Ptr == strType){
			empData = append(empData, data)
			apiRsp.Data = empData
		}else{
			apiRsp.Data = data
		}		
	}		
	strRsp := apiRsp.GetJsonString()	
	c.String(http.StatusOK, strRsp)	
}

//比如这样的json
{
	"error_code": 0,
	"data": [{
		"id": "123456",
		"token": "77888",
		"token_gen_time": 1577413605,		
	}],
	"message": ""
}
那要怎么解析呢成对象呢?比如有Account对象
type Account struct {
	Id            string   `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`	
	Token         string   `protobuf:"bytes,3,opt,name=token" json:"token,omitempty"`
	TokenGenTime  int64    `protobuf:"varint,4,opt,name=token_gen_time,json=tokenGenTime" json:"token_gen_time,omitempty"`	
}

        apiRsp := &ApiRsp{}
		arrAccount  := make([]*model.Account, 0)
		apiRsp.Data = &arrAccount  //解析的时候,要将Data 转为具体的对象数组(切片),不然解析不到对象,注意要使用&arrAccount指针。否则apiRsp.Data这个接口是切片类型,这样的转换失败apiRsp.Data.(*[]*model.Account)
	
		log.Debug("%s rsp: %s", strPath, strRsp)		
		if err := json.Unmarshal([]byte(strRsp), &apiRsp); err != nil {
			log.Error("loginRes Unmarshal error", err)
			return
		}	
		//g_account = arrAccount[0] //这是一种方法
		arrData, ok := apiRsp.Data.(*[]*model.Account) 
if ok{
    g_account = (*arrData)[0]   //这也是一种方法

}
		//strType := reflect.TypeOf(apiRsp.Data).String()		
		

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章