中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

國(guó)外效果超炫網(wǎng)站北京seo優(yōu)化診斷

國(guó)外效果超炫網(wǎng)站,北京seo優(yōu)化診斷,新手建網(wǎng)站,024 網(wǎng)站推廣目錄 背景 框架 ginkgo初始化 抓包&運(yùn)行腳本 目錄說明 ∮./business ∮./conf ∮./utils ∮./testcase testcase 用例目錄結(jié)構(gòu)規(guī)則 示例 實(shí)現(xiàn)思路 解析Har數(shù)據(jù) 定義結(jié)構(gòu)體 解析到j(luò)son 轉(zhuǎn)換請(qǐng)求數(shù)據(jù) 轉(zhuǎn)換請(qǐng)求 轉(zhuǎn)換請(qǐng)求參數(shù) 寫業(yè)務(wù)請(qǐng)求數(shù)據(jù) 寫gotest測(cè)試…

目錄

背景

框架

ginkgo初始化

抓包&運(yùn)行腳本

目錄說明

∮./business

∮./conf

∮./utils

∮./testcase

testcase 用例目錄結(jié)構(gòu)規(guī)則

?示例

實(shí)現(xiàn)思路

解析Har數(shù)據(jù)

定義結(jié)構(gòu)體

解析到j(luò)son

轉(zhuǎn)換請(qǐng)求數(shù)據(jù)

轉(zhuǎn)換請(qǐng)求

轉(zhuǎn)換請(qǐng)求參數(shù)

寫業(yè)務(wù)請(qǐng)求數(shù)據(jù)

寫gotest測(cè)試用例數(shù)據(jù)

初始化寫入suit文件

格式化測(cè)試文件

install生成的業(yè)務(wù)請(qǐng)求目錄

格式化響應(yīng)斷言

可能遇到的問題

完整代碼

詳細(xì)代碼如下,注釋已經(jīng)給得比較清晰:

?資料獲取方法


背景

之前寫過一篇博客,介紹怎么用Python通過解析抓包數(shù)據(jù),完成自動(dòng)化用例的編寫。最近這段時(shí)間在使用go test,所以就在想能不能也使用代碼來生成自動(dòng)化用例,快速提升測(cè)試用例覆蓋率。說干就干。

框架

首先介紹一下我們使用的測(cè)框架:

項(xiàng)信息安裝備注
GO版本go1.12.9 darwin/amd64
測(cè)試框架ginkgogo get -u github.com/onsi/ginkgo/ginkgo
斷言庫(kù)testify/assertgo get github.com/stretchr/testify官方配套的斷言庫(kù)是gomega

ginkgo初始化

  • 初始化:?cd path/to/package/you/want/to/test && ginkgo bootstrap
  • 創(chuàng)建示例用例:ginkgo generate?(需要手動(dòng)添加測(cè)試用例)
  • 運(yùn)行測(cè)試:?go testor?ginkgo

注:-v加上參數(shù)可打印運(yùn)行信息

抓包&運(yùn)行腳本

  • 使用抓包工具(如Charles)抓包,把數(shù)據(jù)包導(dǎo)出為har格式,保存在當(dāng)前目錄下
    • 如何安裝抓包工具在本文就不贅述了,抓包,過濾出想要的數(shù)據(jù),導(dǎo)出,保存的格式注意選擇為har

  • 根據(jù)實(shí)際情況修改全局變量信息,如bizBaseFolder、serverName、userFile等
  • 使用go run gentest.go運(yùn)行腳本即可

目錄說明

然后我們一起來了解一下我們的目錄結(jié)構(gòu)定義。

∮./business

業(yè)務(wù)封裝,封裝具體的請(qǐng)求及測(cè)試數(shù)據(jù)

∮./conf

配置信息及接口請(qǐng)求參數(shù)初始化封裝

∮./utils

公共函數(shù)封裝

∮./testcase

接口測(cè)試用例目錄

testcase 用例目錄結(jié)構(gòu)規(guī)則

基本原則:?根據(jù)項(xiàng)目、模塊、接口功能逐級(jí)區(qū)分,建議最多3層目錄層級(jí)

?示例
  1. 軟件測(cè)試論壇項(xiàng)目組/論壇項(xiàng)目/帖子模塊/創(chuàng)建帖子接口:
    • CN_TestBBS/bbs/post/post_test.go
  2. 基礎(chǔ)賬號(hào)項(xiàng)目/首頁項(xiàng)目/白名單接口:
    • CN_account/homepage/whitelist_test.go

實(shí)現(xiàn)思路

按照har文件的JSON結(jié)構(gòu)定義對(duì)應(yīng)的結(jié)構(gòu)體,然后解析數(shù)據(jù),生成請(qǐng)求數(shù)據(jù),生成斷言數(shù)據(jù),初始化測(cè)試套suite,格式化代碼,初始化包引用信息。

解析Har數(shù)據(jù)

定義結(jié)構(gòu)體
Log struct {version stringcreator stringEntries []struct {startedDateTime stringtime            stringRequest         struct {...
解析到j(luò)son
func UnpackHar(har []byte) (logs *Har) {err := json.Unmarshal(har, &logs)if err != nil {fmt.Println(err)}return
}

轉(zhuǎn)換請(qǐng)求數(shù)據(jù)

轉(zhuǎn)換請(qǐng)求
轉(zhuǎn)換請(qǐng)求參數(shù)

GET

// 格式化請(qǐng)求參數(shù)為標(biāo)準(zhǔn)請(qǐng)求string
getReqParam := make(map[string]interface{}, 1)
if len(v.Request.QueryString) > 0 {for _, query := range v.Request.QueryString {getReqParam[query.Name] = query.Value}
}
// 獲取postReq數(shù)據(jù)
postReqParamStr := v.Request.PostData.Textif v.Request.Method == "GET" {paramstr = genGetParam(InterfaceName, getReqParam)
}
func genGetParam(interfaceName string, param map[string]interface{}) (formatParam string) {// 對(duì)于請(qǐng)求參數(shù)的value值為 數(shù)組if len(param) > 0 {for k, v := range param {switch vv := v.(type) {case []interface{}:fmt.Sprintf(k, "is an array:", vv)temp, _ := json.Marshal(param)formatParam = fmt.Sprintf("%sParam = `%s`", interfaceName, fmt.Sprintf("%v", string(temp)))returndefault:// fmt.Println(k, "is of a type didn't handle")}}}temp, _ := json.Marshal(param)formatParam = fmt.Sprintf(`%sParam = map[string]interface{} %s`, interfaceName, fmt.Sprintf("%v", string(temp)))return
}

POST

postReqParamStr := v.Request.PostData.Textif v.Request.Method == "POST" {paramstr = genPostParam(InterfaceName, postReqParamStr)
}
func genPostParam(interfaceName string, postReqParamStr string) (formatParam string) {// formatParam = fmt.Sprintf(`%sParam = map[string]interface{} %s`, interfaceName, param)// fmt.Sprintf("%v", string(temp))postReqParam := make(map[string]interface{}, 1)if len(postReqParamStr) > 0 {// 判斷第一個(gè)字符是否為{}, 做傳遞數(shù)據(jù)為數(shù)組[]的兼容if []rune(postReqParamStr)[0] == '{' {var x interface{}err := json.Unmarshal([]byte(postReqParamStr), &x)if err != nil {fmt.Println("err", err)}postReqParam = x.(map[string]interface{})// fmt.Println(postReqParam)// 判斷value中是否存在數(shù)組for k, v := range postReqParam {switch vv := v.(type) {// switch vv := v.(type) {case []interface{}:fmt.Sprintf(k, "is an array:", vv)// param[k] = fmt.Sprintf("`%s`", vv)temp, _ := json.Marshal(postReqParam)formatParam = fmt.Sprintf("%sParam = `%s`", interfaceName, fmt.Sprintf("%v", string(temp)))paramType = "string"returndefault:formatParam = genGetParam(interfaceName, postReqParam)// fmt.Println(k, "is of a type didn't handle")}}// 如果為數(shù)組,做如下處理} else {var y []interface{}err := json.Unmarshal([]byte(postReqParamStr), &y)if err != nil {fmt.Println("err", err)}postReqParam = y[0].(map[string]interface{})temp, _ := json.Marshal(postReqParam)// 聲明請(qǐng)求類型paramType = "[]map[string]interface{}"formatParam = fmt.Sprintf(`%sParam =[]map[string]interface{}{%s}`, interfaceName, string(temp))// 無法使用 判斷類型 Param := utils.MapDeepCopy(Hebinz123.XlppcPlaylistApiV1RemarkDelParam)}}// temp, _ := json.Marshal(param)// formatParam = fmt.Sprintf(`%sParam = map[string]interface{} %s`, interfaceName, fmt.Sprintf("%v", string(temp)))return
}

寫業(yè)務(wù)請(qǐng)求數(shù)據(jù)

寫gotest測(cè)試用例數(shù)據(jù)

格式化請(qǐng)求參數(shù)為標(biāo)準(zhǔn)請(qǐng)求string。

初始化寫入suit文件

這里有一個(gè)注意點(diǎn),Test后緊接的數(shù)據(jù)必須是大寫。

格式化測(cè)試文件

使用goimports庫(kù)初始化導(dǎo)入數(shù)據(jù)包。

install生成的業(yè)務(wù)請(qǐng)求目錄

使用go install目錄生成導(dǎo)入業(yè)務(wù)請(qǐng)求目錄

格式化響應(yīng)斷言

使用類型判斷格式化接口返回?cái)?shù)據(jù)為標(biāo)準(zhǔn)斷言string。

可能遇到的問題

  • 初始化讀取文件的存儲(chǔ)buf的size和其實(shí)際大小不一致時(shí),json 解析出錯(cuò)“invalid character '\x00' after top-level value”
  • go install 執(zhí)行失敗,導(dǎo)致測(cè)試用例無法找到其依賴包
  • get請(qǐng)求,post請(qǐng)求參數(shù)在har文件中的存儲(chǔ)方式不一致,獲取數(shù)據(jù)的方式差別很大
  • 域名及接口命名規(guī)則不一致,-、.等等風(fēng)格不一致
  • 測(cè)試suite 緊接Test后方的字符需為大寫的字母,否則服務(wù)無法被發(fā)現(xiàn),所以需要做大小寫轉(zhuǎn)換

完整代碼

詳細(xì)代碼如下,注釋已經(jīng)給得比較清晰:

package mainimport ("encoding/base64""encoding/json""fmt""os""os/exec""path/filepath""strings"
)var (baseDomain         = "test.bbs.com"    // 測(cè)試域名,用于切割出請(qǐng)求路徑bizBaseFolder      = "business/CN_bbs" //業(yè)務(wù)請(qǐng)求目錄testCaseBaseFolder = "testcase/CN_bbs" // 測(cè)試用例目錄serverName         = "cinecismGo"      // 服務(wù)名paramType          = ""
)func main() {userFile := "20190917-cinecismgo.har" // 抓包文件地址fl, err := os.Open(userFile)if err != nil {fmt.Println(userFile, err)return}defer fl.Close()// 讀取har數(shù)據(jù)fileInfo, err := fl.Stat()buf := make([]byte, fileInfo.Size()) // “invalid character '\x00' after top-level value”fl.Read(buf)data := UnpackHar(buf)for _, v := range data.Log.Entries {// 每一個(gè)循環(huán)初始化請(qǐng)求參數(shù)類型paramType = "map[string]interface{}"paramstr := ""// 初始化 請(qǐng)求path,生成標(biāo)準(zhǔn)請(qǐng)求接口名稱pathStr, path := initPath(v.Request.URL)InterfaceName := formatInterfaceName(pathStr)// 格式化請(qǐng)求參數(shù)為標(biāo)準(zhǔn)請(qǐng)求stringgetReqParam := make(map[string]interface{}, 1)if len(v.Request.QueryString) > 0 {for _, query := range v.Request.QueryString {getReqParam[query.Name] = query.Value}}// 獲取postReq數(shù)據(jù)postReqParamStr := v.Request.PostData.Textif v.Request.Method == "GET" {paramstr = genGetParam(InterfaceName, getReqParam)}if v.Request.Method == "POST" {paramstr = genPostParam(InterfaceName, postReqParamStr)}// 格式化接口返回?cái)?shù)據(jù)為標(biāo)準(zhǔn)斷言stringtext, _ := base64.StdEncoding.DecodeString(v.Response.Content.Text)responseAssertStr := initAssert(text)// 創(chuàng)建業(yè)務(wù)請(qǐng)求文件、測(cè)試用例文件run(serverName, path, InterfaceName, v.Request.Method, responseAssertStr, paramstr)// 【待補(bǔ)充】handle Headers數(shù)據(jù)// fmt.Println(initHeaders(data))}
}func initAssert(text []byte) (responseAssertStr string) {if len(text) > 0 {var Response interface{}err := json.Unmarshal(text, &Response)if err != nil {fmt.Println("err", err)}responseMap := Response.(map[string]interface{})res := []string{}for k, v := range responseMap {switch vv := v.(type) {case string:// fmt.Println(k, "is string", vv)res = append(res, fmt.Sprintf("%s, _ := js.Get(\"%s\").String() \n assert.Equal(%s, `%v`)", k, k, k, string(vv)))case int64:// fmt.Println(k, "is int", vv)res = append(res, fmt.Sprintf("%s, _ := js.Get(\"%s\").Int() \n assert.Equal(%s, %v)", k, k, k, string(vv)))case float64:// fmt.Println(k, "is float64", vv)res = append(res, fmt.Sprintf("%s, _ := js.Get(\"%s\").Int() \n assert.Equal(%s, %v)", k, k, k, vv))case bool:// fmt.Println(k, "is bool", vv)res = append(res, fmt.Sprintf("%s, _ := js.Get(\"%s\").Bool() \n assert.Equal(%s, %v)", k, k, k, vv))case []interface{}:// fmt.Println(k, "is an array:", vv)res = append(res, fmt.Sprintf("// Key【%s】的子層級(jí)的value值未生成斷言,系多層級(jí)數(shù)組數(shù)據(jù),具體值如下:", k))res = append(res, fmt.Sprintf("// %v ", vv))case map[string]interface{}:// fmt.Println(k, "is an map:", vv)temp, _ := json.Marshal(vv)res = append(res, fmt.Sprintf("// Key【%s】的子層級(jí)value值未生成斷言,系多層級(jí)Map數(shù)據(jù),具體值如下:", k))res = append(res, fmt.Sprintf("// %v ", string(temp)))default:// fmt.Println(k, "is of a type didn't handle", vv)}responseAssertStr = strings.Join(res, "\n")}}return
}func initPath(URL string) (pathStr, path string) {pathStr = strings.Split(URL, baseDomain)[1]if strings.Contains(pathStr, "?") {pathStr = strings.Split(pathStr, "?")[0]path = strings.Split(pathStr, "?")[0]} else {path = pathStr}if strings.Contains(pathStr, ".") {pathStr = strings.Replace(pathStr, ".", "/", 10)pathStr = strings.Replace(pathStr, "-", "/", 10)}// fmt.Println(path)// fmt.Println("pathStr", pathStr)return
}func run(serverName, path, InterfaceName, method, responseAssertStr string, Param string) {// 初始化測(cè)試文件InterfaceFilepath := filepath.Join(bizBaseFolder, serverName)Testcasefilepath := filepath.Join(testCaseBaseFolder, serverName)InterfaceFileame := InterfaceName + ".go"Testcasefilename := InterfaceName + "_test.go"// 創(chuàng)建并寫入標(biāo)準(zhǔn)請(qǐng)求信息file, err := createFile(InterfaceFilepath, InterfaceFileame)if err != nil {fmt.Println("createInterfaceFile", err)}writeParam(file, serverName, []string{Param})writeReq(file, InterfaceName, path, method)defer file.Close()// 創(chuàng)建并寫入測(cè)試用例信息file1, err := createFile(Testcasefilepath, Testcasefilename)if err != nil {fmt.Println("createTestcasefile", err)}// 寫入suit文件initTestsuit(serverName)// 寫入測(cè)試用例writeTestcase(file1, serverName, InterfaceName, responseAssertStr)defer file1.Close()// 格式化測(cè)試文件exec.Command("goimports", "-w", InterfaceFilepath).Run()exec.Command("goimports", "-w", Testcasefilepath).Run()// 導(dǎo)入InterfaceFilepathexec.Command("go", "install", InterfaceFilepath).Run()
}func initHeaders(har *Har) map[string]string {var headers = make(map[string]string)// fmt.Println(len(har.Log.Entries[0].Request.Headers))for _, v := range har.Log.Entries[0].Request.Headers {headers[v.Name] = v.Value}return headers
}func createFile(filepaths, filename string) (file *os.File, err error) {os.MkdirAll(filepaths, 0777)file, err = os.Create(filepath.Join(filepaths, filename))return
}func createInterfaceFile(path, filename string) (file *os.File, err error) {filename = filename + ".go"filepath := bizBaseFolder + "/" + path + "/"os.MkdirAll(filepath, 0777)file, err = os.Create(filepath + filename)return
}func createTestcasefile(path, filename string) (file *os.File, err error) {filename = filename + "_test.go"filepath := testCaseBaseFolder + "/" + path + "/"os.MkdirAll(filepath, 0777)file, err = os.Create(filepath + filename)return
}func initTestsuit(serverName string) {filename := serverName + "_suite_test.go"filepath := testCaseBaseFolder + "/" + serverName + "/"os.MkdirAll(filepath, 0777)file, err := os.Create(filepath + filename)if err != nil {fmt.Println("initTestsuit Error", err)}// Testsuite后的 首字母需大寫,否則suite無法正常檢索到testcasefile.WriteString(fmt.Sprintf(`package %s_testimport ("testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega")func Test%s(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "%s Suite")}`, serverName, Capitalize(serverName), serverName))
}func writeTestcase(file *os.File, serverName, InterfaceName, responseAssertStr string) {// 接口引入路徑 【服務(wù)名稱.接口名稱】interfaceImportPath := serverName + "." + InterfaceName// 接口標(biāo)準(zhǔn)請(qǐng)求參數(shù) 【接口名稱Param】paramImportPath := interfaceImportPath + "Param"// 接口標(biāo)準(zhǔn)請(qǐng)求參數(shù)拷貝,請(qǐng)求參數(shù)為非標(biāo)準(zhǔn)【map[string]interface{}】類型時(shí),該參數(shù)為空tempParamStr := ""// 是否使用mapDeepCopy,請(qǐng)求參數(shù)為非標(biāo)準(zhǔn)【map[string]interface{}】類型時(shí) 使用mapDeepCopy := ""if paramType != "map[string]interface{}" {tempParamStr = paramImportPath}if paramType == "map[string]interface{}" {tempParamStr = "Param"mapDeepCopy = fmt.Sprintf(`Param := utils.MapDeepCopy(%s)`, paramImportPath)}// fmt.Println("---------------->", paramType)file.WriteString(fmt.Sprintf("package %s_test\n\n", serverName))file.WriteString(`import . "github.com/onsi/ginkgo"`)file.WriteString("\n\n")file.WriteString(fmt.Sprintf(`var _ = Describe("%s", func() {headers := common.EntireHeaderParamassert := assert.New(GinkgoT())BeforeEach(func() {By("begin test")})JustBeforeEach(func() {By("just say start")})AfterEach(func() {By("end test")})Context("%s", func() {It("正常%s", func() {%sret, resp, _ := %s(%s, headers)assert.Equal(ret.StatusCode, 200)js, errs := simplejson.NewJson(resp)if errs != nil {panic(errs)}%s})})})`, serverName, InterfaceName, InterfaceName, mapDeepCopy, interfaceImportPath, tempParamStr, responseAssertStr))
}func writeParam(file *os.File, serverName string, params []string) {file.WriteString(fmt.Sprintf("package %s", serverName))file.WriteString("\n\n\n")file.WriteString("var (")for _, param := range params {file.WriteString(param)}file.WriteString(")")file.WriteString("\n\n\n")
}func writeReq(file *os.File, InterfaceName, path, method string) {file.WriteString(fmt.Sprintf(`func %s(param %s, header map[string]string) (ret gorequest.Response, content []byte, result string) {path := "%s"url := CN_bbs.TESTSERVERDOMAIN + pathret, content = common.Common%s(url, param, header)fmt.Println(ret.Request.URL)// js, _ := simplejson.NewJson([]byte(content))//result, _ = js.Get("result").String()return}`, InterfaceName, paramType, path, method))
}func genGetParam(interfaceName string, param map[string]interface{}) (formatParam string) {// 對(duì)于請(qǐng)求參數(shù)的value值為 數(shù)組if len(param) > 0 {for k, v := range param {switch vv := v.(type) {case []interface{}:fmt.Sprintf(k, "is an array:", vv)temp, _ := json.Marshal(param)// 如果是數(shù)組格式,直接當(dāng)作字符串處理(map[]interface{}格式無法表示該類型參數(shù))formatParam = fmt.Sprintf("%sParam = `%s`", interfaceName, fmt.Sprintf("%v", string(temp)))returndefault:// fmt.Println(k, "is of a type didn't handle")}}}temp, _ := json.Marshal(param)formatParam = fmt.Sprintf(`%sParam = map[string]interface{} %s`, interfaceName, fmt.Sprintf("%v", string(temp)))return
}func genPostParam(interfaceName string, postReqParamStr string) (formatParam string) {// formatParam = fmt.Sprintf(`%sParam = map[string]interface{} %s`, interfaceName, param)// fmt.Sprintf("%v", string(temp))postReqParam := make(map[string]interface{}, 1)if len(postReqParamStr) > 0 {// 判斷第一個(gè)字符是否為{}, 做傳遞數(shù)據(jù)為數(shù)組[]的兼容if []rune(postReqParamStr)[0] == '{' {var x interface{}err := json.Unmarshal([]byte(postReqParamStr), &x)if err != nil {fmt.Println("err", err)}postReqParam = x.(map[string]interface{})// fmt.Println(postReqParam)// 判斷value中是否存在數(shù)組for k, v := range postReqParam {switch vv := v.(type) {// switch vv := v.(type) {case []interface{}:fmt.Sprintf(k, "is an array:", vv)// param[k] = fmt.Sprintf("`%s`", vv)temp, _ := json.Marshal(postReqParam)formatParam = fmt.Sprintf("%sParam = `%s`", interfaceName, fmt.Sprintf("%v", string(temp)))paramType = "string"returndefault:formatParam = genGetParam(interfaceName, postReqParam)// fmt.Println(k, "is of a type didn't handle")}}// 如果為數(shù)組,做如下處理} else {var y []interface{}err := json.Unmarshal([]byte(postReqParamStr), &y)if err != nil {fmt.Println("err", err)}postReqParam = y[0].(map[string]interface{})temp, _ := json.Marshal(postReqParam)// 聲明請(qǐng)求類型paramType = "[]map[string]interface{}"formatParam = fmt.Sprintf(`%sParam =[]map[string]interface{}{%s}`, interfaceName, string(temp))// 無法使用 判斷類型 Param := utils.MapDeepCopy(Hebinz123.CNppcPlaylistApiV1RemarkDelParam)}}// temp, _ := json.Marshal(param)// formatParam = fmt.Sprintf(`%sParam = map[string]interface{} %s`, interfaceName, fmt.Sprintf("%v", string(temp)))return
}func formatInterfaceName(path string) (InterfaceName string) {paths := strings.Split(path, "/")for k, v := range paths {paths[k] = Capitalize(v)}InterfaceName = strings.Join(paths, "")return
}// Capitalize 字符首字母大寫
func Capitalize(str string) string {var upperStr stringvv := []rune(str)for i := 0; i < len(vv); i++ {if i == 0 {if vv[i] >= 97 && vv[i] <= 122 { // 判斷是否是小寫字母vv[i] -= 32 // string的碼表相差32位upperStr += string(vv[i])} else {fmt.Println("Not begins with lowercase letter,")return str}} else {upperStr += string(vv[i])}}return upperStr
}// Har Logs 解析
type Har struct {Log struct {version stringcreator stringEntries []struct {startedDateTime stringtime            stringRequest         struct {Method      stringURL         stringhttpVersion stringCookies     []stringHeaders     []struct {Name  stringValue string}QueryString []struct {Name  stringValue string}PostData struct {MimeType stringText     string}headersSize int32bodySize    int32}Response struct {_charlesStatus stringStatus         int32StatusText     stringhttpVersion    stringcookies        []stringHeaders        []struct {Name  stringValue string}Content struct {size     int32mimeType stringText     stringEncoding string}redirectURL stringheadersSize intbodySize    int}serverIPAddress stringcache           map[string]stringtimings         map[string]int32}}
}// UnpackHar 解析 har
func UnpackHar(har []byte) (logs *Har) {err := json.Unmarshal(har, &logs)if err != nil {fmt.Println(err)}return
}

文中可能存在描述不正確,歡迎大神們指正補(bǔ)充!

感謝閱讀,如果覺得對(duì)你有幫助,就在右下角點(diǎn)個(gè)贊吧,感謝!

合抱之木,生于毫末;九層之臺(tái),起于累土;千里之行,始于足下。


?資料獲取方法

【留言777】

各位想獲取源碼等教程資料的朋友請(qǐng)點(diǎn)贊 + 評(píng)論 + 收藏,三連!

三連之后我會(huì)在評(píng)論區(qū)挨個(gè)私信發(fā)給你們~

http://www.risenshineclean.com/news/48947.html

相關(guān)文章:

  • 河北網(wǎng)站建設(shè)排名優(yōu)化哪家專業(yè)
  • 網(wǎng)站怎樣免費(fèi)推廣網(wǎng)絡(luò)營(yíng)銷專業(yè)課程
  • 杭州裝飾網(wǎng)站建設(shè)互聯(lián)網(wǎng)營(yíng)銷的方法
  • 有什么做動(dòng)畫的網(wǎng)站seo的英文全稱是什么
  • 男生做網(wǎng)站編輯全球搜是什么公司
  • wordpress 插件 kf5谷歌關(guān)鍵詞優(yōu)化怎么做
  • wex5做視頻網(wǎng)站廣東疫情最新數(shù)據(jù)
  • 太原整站優(yōu)化搜索優(yōu)化軟件
  • 網(wǎng)站cname解析seo排名優(yōu)化培訓(xùn)網(wǎng)站
  • 百度seo優(yōu)化公司旺道網(wǎng)站排名優(yōu)化
  • python怎么做專門的手機(jī)網(wǎng)站百度免費(fèi)網(wǎng)站制作
  • 微信企業(yè)網(wǎng)站文件外鏈
  • 好看免費(fèi)的ppt模板下載做百度seo
  • 商務(wù)型企業(yè)網(wǎng)站建設(shè)近期的重大新聞
  • 樂清網(wǎng)站建設(shè)費(fèi)用網(wǎng)上培訓(xùn)機(jī)構(gòu)
  • 網(wǎng)站加密傳輸怎么做搜索引擎優(yōu)化需要多少錢
  • 瑞麗網(wǎng)站建設(shè)百度網(wǎng)站排名優(yōu)化價(jià)格
  • 大連哪家公司做網(wǎng)站網(wǎng)絡(luò)推廣的調(diào)整和優(yōu)化
  • 網(wǎng)站建設(shè)銷售發(fā)展前景seo百家論壇
  • 商城網(wǎng)站 價(jià)格濟(jì)寧百度推廣價(jià)格
  • 做網(wǎng)站前端后端ui什么意思谷歌優(yōu)化排名怎么做
  • 廣東省城鄉(xiāng)建設(shè)和管理委員會(huì)網(wǎng)站谷歌瀏覽器下載電腦版
  • 家居網(wǎng)站源碼軟文推送
  • 購(gòu)買網(wǎng)站服務(wù)如何做支出seo是什么崗位簡(jiǎn)稱
  • 想學(xué)網(wǎng)站建設(shè)開發(fā)代運(yùn)營(yíng)一般收費(fèi)
  • 蚌埠公司做網(wǎng)站網(wǎng)絡(luò)推廣員為什么做不長(zhǎng)
  • 做的網(wǎng)站怎么放在網(wǎng)上百度的人工客服電話
  • h5頁面生成青島seo精靈
  • 微信朋友圈推廣平臺(tái)seo銷售代表招聘
  • golang做網(wǎng)站怎么樣微信群免費(fèi)推廣平臺(tái)