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()