日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

基于Golang的对象序列化的程序包开发——myJsonMarshal

發(fā)布時(shí)間:2023/11/28 生活经验 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Golang的对象序列化的程序包开发——myJsonMarshal 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基于Golang的對(duì)象序列化的程序包開發(fā)——myJsonMarshal【閱讀時(shí)間:約10分鐘】

  • 一、對(duì)象序列化概述
  • 二、系統(tǒng)環(huán)境&項(xiàng)目介紹
    • 1.系統(tǒng)環(huán)境
    • 2.項(xiàng)目的任務(wù)要求
  • 三、具體程序設(shè)計(jì)及Golang代碼實(shí)現(xiàn)
    • 1.程序設(shè)計(jì)
    • 2.JsonMarshal函數(shù)
    • 3.Marshal函數(shù)
    • 4.StringTrans函數(shù)
    • 5.StructTrans函數(shù)
    • 6.MapTrans函數(shù)
    • 7.SliceTrans函數(shù)
    • 8.ArrayTrans函數(shù)
    • 9.PtrTrans函數(shù)
  • 四、程序測試
    • 1.封裝并使用程序包
    • 2.功能測試
    • 3.單元測試
  • 五、中文 api 文檔
  • 六、完整代碼
  • 七、References

一、對(duì)象序列化概述

將一個(gè)對(duì)象寫成特定文本格式的字符流,稱為序列化。在本次開發(fā)的程序包myJsonMarshal中,我們可以利用它將將結(jié)構(gòu)數(shù)據(jù)格式化為 json 字符流。


二、系統(tǒng)環(huán)境&項(xiàng)目介紹

1.系統(tǒng)環(huán)境

操作系統(tǒng):CentOS7
硬件信息:使用virtual box配置虛擬機(jī)(內(nèi)存3G、磁盤30G)
編程語言:GO 1.15.2

2.項(xiàng)目的任務(wù)要求

  1. 參考官方 encoding/json 包 Marshal 函數(shù),將結(jié)構(gòu)數(shù)據(jù)格式化為 json 字符流
    • 必須導(dǎo)出 func JsonMarshal(v interface{}) ([]byte, error)
    • 可以參考、甚至復(fù)制原來的代碼
    • 支持字段的標(biāo)簽(Tag),標(biāo)簽滿足 mytag:"你自己的定義"
    • 不允許使用第三方包
  2. 包必須包括以下內(nèi)容:
    • 生成的中文 api 文檔
    • 有較好的 Readme 文件,包括一個(gè)簡單的使用案例
    • 每個(gè)go文件必須有對(duì)應(yīng)的測試文件



三、具體程序設(shè)計(jì)及Golang代碼實(shí)現(xiàn)

1.程序設(shè)計(jì)

本次程序包開發(fā)實(shí)現(xiàn)較為簡單,只要根據(jù)輸入的結(jié)構(gòu)數(shù)據(jù)的類型,逐步分為多種基礎(chǔ)的類型,如int、string和array等,然后將輸入數(shù)據(jù)及其類型轉(zhuǎn)為byte[],再轉(zhuǎn)為json格式的字符流即可。
其中,參考官方 encoding/json 包 Marshal 函數(shù),在判斷數(shù)據(jù)類型時(shí)用到了reflect程序包。
myJsonMarshal程序包的函數(shù)架構(gòu)如下:

下面按照myJsonMarshal程序包的源碼順序來依次介紹數(shù)據(jù)結(jié)構(gòu)和相關(guān)函數(shù)。

2.JsonMarshal函數(shù)

//JsonMarshal 輸入結(jié)構(gòu)化數(shù)據(jù),返回json字符流和error
func JsonMarshal(v interface{}) ([]byte, error) {b, err := Marshal(v)if err != nil {return nil, err}return b, nil
}

JsonMarshal函數(shù)是本程序包的主要接口,通過輸入結(jié)構(gòu)化數(shù)據(jù),可以返回json字符流和報(bào)錯(cuò)信息error。


3.Marshal函數(shù)

//Marshal 將接口數(shù)據(jù)類型的數(shù)據(jù)轉(zhuǎn)為json字符流
func Marshal(v interface{}) ([]byte, error) {json := reflect.ValueOf(v)typeJson := json.Type()switch typeJson.Kind() {case reflect.Invalid:return []byte("Invalid"), errors.New("Invalid")case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,reflect.Uint64, reflect.Float32, reflect.Float64:return []byte(fmt.Sprintf("%v", json.Interface())), nilcase reflect.String:return StringTrans(v)case reflect.Struct:return StructTrans(v)case reflect.Map:return MapTrans(v)case reflect.Slice:return SliceTrans(v)case reflect.Array:return ArrayTrans(v)case reflect.Ptr:return PtrTrans(v)default:return []byte("unsupportedTypeTrans"), errors.New("unsupportedTypeTrans")}
}

Marshal函數(shù)調(diào)用reflect程序包,通過switch-case語句,將不同接口數(shù)據(jù)類型的數(shù)據(jù)轉(zhuǎn)為json字符流。



4.StringTrans函數(shù)

//StringTrans 將string數(shù)據(jù)轉(zhuǎn)為json字符流
func StringTrans(v interface{}) ([]byte, error) {json := reflect.ValueOf(v)return []byte("\"" + json.String() + "\""), nil
}

StringTrans函數(shù)將string數(shù)據(jù)轉(zhuǎn)為json字符流


5.StructTrans函數(shù)

//StructTrans 將struct數(shù)據(jù)轉(zhuǎn)為json字符流
func StructTrans(v interface{}) ([]byte, error) {json := reflect.ValueOf(v)typeJson := json.Type()b := "{"for i := 0; i < json.NumField(); i++ {if i > 0 {b = b + ","}tag := typeJson.Field(i).Tag.Get("mytag")if tag == "" {b = b + "\"" + typeJson.Field(i).Name + "\":"} else {b = b + "\"" + tag + "\":"}tmp, err := Marshal(json.Field(i).Interface())if err != nil {return nil, err}b = b + string(tmp)}b = b + "}"return []byte(b), nil
}

StructTrans函數(shù)將struct數(shù)據(jù)轉(zhuǎn)為json字符流,并且支持字段的標(biāo)簽(Tag),標(biāo)簽滿足 mytag:"你自己的定義"。如果變量打上了mytag標(biāo)簽,如Name旁邊的 mytag:"name" ,那么轉(zhuǎn)化成的json key就用該標(biāo)簽“name”,否則取變量名作為key。


6.MapTrans函數(shù)

//MapTrans 將map數(shù)據(jù)轉(zhuǎn)為json字符流
func MapTrans(v interface{}) ([]byte, error) {json := reflect.ValueOf(v)i := json.MapRange()first := trueb := "{"for i.Next() {if first {first = false} else {b = b + ","}b = b + "\"" + fmt.Sprintf("\"%v\":", i.Key()) + "\":"tmp, err := Marshal(i.Value().Interface())if err != nil {return nil, err}b = b + string(tmp)}b = b + "}"return []byte(b), nil
}

MapTrans函數(shù)將map數(shù)據(jù)轉(zhuǎn)為json字符流


7.SliceTrans函數(shù)

//SliceTrans 將slice數(shù)據(jù)轉(zhuǎn)為json字符流
func SliceTrans(v interface{}) ([]byte, error) {json := reflect.ValueOf(v)b := "["for i := 0; i < json.Len(); i++ {if i > 0 {b = b + ","}tmp, err := Marshal(json.Index(i).Interface())if err != nil {return nil, err}b = b + string(tmp)}b = b + "]"return []byte(b), nil
}

SliceTrans函數(shù)將slice數(shù)據(jù)轉(zhuǎn)為json字符流



8.ArrayTrans函數(shù)

//ArrayTrans 將array數(shù)據(jù)轉(zhuǎn)為json字符流
func ArrayTrans(v interface{}) ([]byte, error) {json := reflect.ValueOf(v)b := "["for i := 0; i < json.Len(); i++ {if i > 0 {b = b + ","}tmp, err := Marshal(json.Index(i).Interface())if err != nil {return nil, err}b = b + string(tmp)}b = b + "]"return []byte(b), nil
}

ArrayTrans函數(shù)將array數(shù)據(jù)轉(zhuǎn)為json字符流


9.PtrTrans函數(shù)

//PtrTrans 將ptr數(shù)據(jù)轉(zhuǎn)為json字符流
func PtrTrans(v interface{}) ([]byte, error) {json := reflect.ValueOf(v)return Marshal(json.Elem().Interface())
}

StringTrans函數(shù)將ptr數(shù)據(jù)轉(zhuǎn)為json字符流,指針變量編碼時(shí)自動(dòng)轉(zhuǎn)換為它所指向的值。



四、程序測試

1.封裝并使用程序包

將項(xiàng)目myJsonMarshal的myJsonMarshal.go文件的main函數(shù)注釋掉,package改為package myJsonMarshal,然后執(zhí)行如下指令:

go build

在其他路徑下建立main.go,并調(diào)用myJsonMarshal.JsonMarshal函數(shù)即可。



2.功能測試

功能測試主要從用戶角度測試程序包的功能,步驟如下:
創(chuàng)建main.go文件,內(nèi)容如下(結(jié)構(gòu)化數(shù)據(jù)類型及其數(shù)值可自定義):

package mainimport ("fmt""github.com/user/myJsonMarshal"
)type Stu struct {Name  string `mytag:"name"`Age   intHIgh  boolClass *Class `mytag:"class"`
}type Class struct {Name  stringGrade int
}func main() {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串stu := Stu{Name: "張三",Age:  18,HIgh: true,}//指針變量cla := new(Class)cla.Name = "1班"cla.Grade = 3stu.Class = cla//Marshal失敗時(shí)err!=niljsonStu, err := myJsonMarshal.JsonMarshal(stu)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}//jsonStu是[]byte類型,轉(zhuǎn)化成string類型便于查看fmt.Println(string(jsonStu))
}

運(yùn)行結(jié)果:

由此可知程序包的功能測試正常,符合的程序包的幾個(gè)要求:
①結(jié)構(gòu)化數(shù)據(jù)轉(zhuǎn)為json字符流
②支持字段的標(biāo)簽(Tag),標(biāo)簽滿足 mytag:"你自己的定義"
③指針變量編碼時(shí)自動(dòng)轉(zhuǎn)換為它所指向的值



3.單元測試

單元測試主要從程序員角度,對(duì)程序包的具體函數(shù)進(jìn)行測試。
建立myJsonMarshal_test.go文件,對(duì)程序包的每個(gè)函數(shù)進(jìn)行單元測試如下,代碼如下:

package myJsonMarshalimport ("fmt""testing"
)type Stu struct {Name  string `mytag:"name"`Age   intHIgh  boolClass *Class `mytag:"class"`
}type Class struct {Name  stringGrade int
}func Test_JsonMarshal(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串stu := Stu{Name: "張三",Age:  18,HIgh: true,}//指針變量cla := new(Class)cla.Name = "1班"cla.Grade = 3stu.Class = cla//Marshal失敗時(shí)err!=niljsonStu, err := JsonMarshal(stu)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "{\"name\":\"張三\",\"Age\":18,\"HIgh\":true,\"class\":{\"Name\":\"1班\",\"Grade\":3}}"got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}func Test_Marshal(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串stu := Stu{Name: "張三",Age:  18,HIgh: true,}//指針變量cla := new(Class)cla.Name = "1班"cla.Grade = 3stu.Class = cla//Marshal失敗時(shí)err!=niljsonStu, err := Marshal(stu)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "{\"name\":\"張三\",\"Age\":18,\"HIgh\":true,\"class\":{\"Name\":\"1班\",\"Grade\":3}}"got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}func Test_StringTrans(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串test := "unit test"//Marshal失敗時(shí)err!=niljsonStu, err := StringTrans(test)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "\"unit test\""got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}func Test_StructTrans(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串test := Class{Name:  "1班",Grade: 3,}//Marshal失敗時(shí)err!=niljsonStu, err := StructTrans(test)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "{\"Name\":\"1班\",\"Grade\":3}"got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}func Test_MapTrans(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串test := map[string]int{"one":   1,"two":   2,"three": 3,}//Marshal失敗時(shí)err!=niljsonStu, err := MapTrans(test)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "{\"\"one\":\":1,\"\"two\":\":2,\"\"three\":\":3}"got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}func Test_SliceTrans(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串test := []int{1, 2, 3}//Marshal失敗時(shí)err!=niljsonStu, err := SliceTrans(test)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "[1,2,3]"got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}func Test_ArrayTrans(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串test := [3]int{1, 2, 3}//Marshal失敗時(shí)err!=niljsonStu, err := ArrayTrans(test)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "[1,2,3]"got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}func Test_PtrTrans(t *testing.T) {//實(shí)例化一個(gè)數(shù)據(jù)結(jié)構(gòu),用于生成json字符串test := new(Class)test.Name = "1班"test.Grade = 3//Marshal失敗時(shí)err!=niljsonStu, err := PtrTrans(test)if err != nil {fmt.Println("生成json字符串錯(cuò)誤")}want := "{\"Name\":\"1班\",\"Grade\":3}"got := string(jsonStu)if got != want {t.Errorf("\n got %s\n want %s\n", got, want)}
}

在執(zhí)行單元測試時(shí),我們可以像上一次博客一樣【博客】,在vscode中便捷地對(duì)每個(gè)函數(shù)進(jìn)行test run,當(dāng)編寫單個(gè)函數(shù)的測試函數(shù)時(shí),筆者更推薦這種方式。
當(dāng)然,也可以像本次博客一樣,在項(xiàng)目目錄下,輸入以下指令:

go test -v myJsonMarshal_test.go myJsonMarshal.go 

單元測試結(jié)果如下:

[henryhzy@localhost myJsonMarshal]$ go test -v myJsonMarshal_test.go myJsonMarshal.go 
=== RUN   Test_JsonMarshal
--- PASS: Test_JsonMarshal (0.00s)
=== RUN   Test_Marshal
--- PASS: Test_Marshal (0.00s)
=== RUN   Test_StringTrans
--- PASS: Test_StringTrans (0.00s)
=== RUN   Test_StructTrans
--- PASS: Test_StructTrans (0.00s)
=== RUN   Test_MapTrans
--- PASS: Test_MapTrans (0.00s)
=== RUN   Test_SliceTrans
--- PASS: Test_SliceTrans (0.00s)
=== RUN   Test_ArrayTrans
--- PASS: Test_ArrayTrans (0.00s)
=== RUN   Test_PtrTrans
--- PASS: Test_PtrTrans (0.00s)
PASS
ok  	command-line-arguments	0.002s



五、中文 api 文檔

首先安裝godoc如下:

git clone https://github.com/golang/tools $GOPATH/src/golang.org/x/tools
go build golang.org/x/tools

在項(xiàng)目myJsonMarshal所在目錄下,執(zhí)行如下指令:

go install
go doc
godoc -url="pkg/github.com/user/myJsonMarshal" > API.html

便會(huì)在當(dāng)前目錄下生成API.html文件:

【注意:程序包的函數(shù)名開頭應(yīng)為大寫字母,對(duì)于函數(shù)A若含有注釋,注釋的開頭也應(yīng)為//A。】



六、完整代碼

具體代碼可見gitee倉庫:gitee


七、References

  1. 課程博客
  2. go json.Marshal 編組函數(shù)講解
  3. 官方 encoding/json 包

總結(jié)

以上是生活随笔為你收集整理的基于Golang的对象序列化的程序包开发——myJsonMarshal的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。