日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
創(chuàng)新互聯(lián)GO教程:Go語(yǔ)言自定義數(shù)據(jù)文件

對(duì)一個(gè)程序非常普遍的需求包括維護(hù)內(nèi)部 數(shù)據(jù)結(jié)構(gòu),為數(shù)據(jù)交換提供導(dǎo)入導(dǎo)出功能,也支持使用外部工具來(lái)處理數(shù)據(jù)。

蘇家屯網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站設(shè)計(jì)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)公司公司2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司。

由于我們這里的關(guān)注重點(diǎn)是文件處理,因此我們純粹只關(guān)心如何從程序內(nèi)部數(shù)據(jù)結(jié)構(gòu)中讀取數(shù)據(jù)并將其寫(xiě)入標(biāo)準(zhǔn)和自定義格式的文件中,以及如何從標(biāo)準(zhǔn)和自定義格式文件中讀取數(shù)據(jù)并寫(xiě)入程序的內(nèi)部數(shù)據(jù)結(jié)構(gòu)中。

本節(jié)中,我們會(huì)為所有的例子使用相同的數(shù)據(jù),以便直接比較不同的文件格式。所有的代碼都來(lái)自 invoicedate 程序(在 invoicedata 目錄中的 invoicedata.go > gob.go、inv.go、jsn.go、txt.go 和 xml.go 等文件中)。大家可以從我的網(wǎng)盤(pán)(鏈接: https://pan.baidu.com/s/1j22QfIScihrauVCVFV6MWw 提取碼: ajrk)下載相關(guān)的代碼。

該程序接受兩個(gè)文件名作為命令行參數(shù),一個(gè)用于讀,另一個(gè)用于寫(xiě)(它們必須是不同的文件)。程序從第一個(gè)文件中讀取數(shù)據(jù)(以其后綴所表示的任何格式),并將數(shù)據(jù)寫(xiě)入第二個(gè)文件(也是以其后綴所表示的任何格式)。

由 invoicedata 程序創(chuàng)建的文件可跨平臺(tái)使用,也就是說(shuō),無(wú)論是什么格式,Windows 上創(chuàng)建的文件都可在 Mac OS X 以及 Linux 上讀取,反之亦然。Gzip 格式壓縮的文件(如 invoices.gob.gz)可以無(wú)縫讀寫(xiě)。

這些數(shù)據(jù)由一個(gè) []invoice 組成,也就是說(shuō),是一個(gè)保存了指向 Invoice 值的指針的切片。每一個(gè)發(fā)票數(shù)據(jù)都保存在一個(gè) invoice 類(lèi)型的值中,同時(shí)每一個(gè)發(fā)票數(shù)據(jù)都以 []*Item 的形式保存著 0 個(gè)或者多個(gè)項(xiàng)。

type Invoice struct {
    Id          int
    Customerld  int
    Raised      time.Time
    Due         time.Time
    Paid        bool
    Note        string
    Items       []*Item
}

type Item struct {
    Id       st ring
    Price    float64
    Quantity int
    Note     string
}

這兩個(gè)結(jié)構(gòu)體用于保存數(shù)據(jù)。下表給出了一些非正式的對(duì)比,展示了每種格式下讀寫(xiě)相同的 50000 份隨機(jī)發(fā)票數(shù)據(jù)所需的時(shí)間,以及以該格式所存儲(chǔ)文件的大小。

計(jì)時(shí)按秒計(jì),并向上舍入到最近的十分之一秒。我們應(yīng)該把計(jì)時(shí)結(jié)果認(rèn)為是無(wú)絕對(duì)單位的,因?yàn)椴煌布约安?同負(fù)載情況下該值都不盡相同。大小一欄以千字節(jié)(KB)算,該值在所有機(jī)器上應(yīng)該都是相同的。

對(duì)于該數(shù)據(jù)集,雖然未壓縮文件的大小千差萬(wàn)別,但壓縮文件的大小都驚人的相似。而代碼的 函數(shù)不包括所有格式通用的代碼(例如,那些用于壓縮和解壓縮以及定義結(jié)構(gòu)體的代碼)。

表:各種格式的速度以及大小對(duì)比

后綴 讀取 寫(xiě)入 大小(KiB) 讀/寫(xiě)LOC 格式
.gob 0.3 0.2 7948 21 + 11 =32 Go二進(jìn)制
.gob.gz 0.5 1.5 2589
jsn 4.5 2.2 16283 32+17 = 49 JSON
.jsn.gz 4.5 3.4 2678
.xml 6.7 1.2 18917 45 + 30 = 75 XML
.xml.gz 6.9 2.7 2730
..txt 1.9 1.0 12375 86 + 53 = 139 純文本(UTF-8)
.txt.gz 2.2 2.2 2514
.inv 1.7 3.5 7250 128 + 87 = 215 自定義二進(jìn)制
.inv.gz 1.6 2.6 2400

這些讀寫(xiě)時(shí)間和文件大小在我們的合理預(yù)期范圍內(nèi),除了純文本格式的讀寫(xiě)異??熘?。這得益于 fmt 包優(yōu)秀的打印和掃描函數(shù),以及我們?cè)O(shè)計(jì)的易于解析的自定義文本格式。

對(duì)于 JSON 和 XML 格式,我們只簡(jiǎn)單地存儲(chǔ)了日期部分而非存儲(chǔ)默認(rèn)的 time.Time 值(一個(gè) ISO-8601 日期/時(shí)間字符串),通過(guò)犧牲一些速度和增加一些額外代碼稍微減小了文件的大小。

例如,如果讓JSON代碼自己來(lái)處理time.Time值,它能夠運(yùn)行得更快,并且其代碼行數(shù)與 Go語(yǔ)言二進(jìn)制編碼差不多。

對(duì)于二進(jìn)制數(shù)據(jù),Go語(yǔ)言的二進(jìn)制格式是最便于使用的。它非常快且極端緊湊,所需的代碼非常少,并且相對(duì)容易適應(yīng)數(shù)據(jù)的變化。然而,如果我們使用的自定義類(lèi)型不原生支持 gob 編碼,我們必須讓該類(lèi)型滿(mǎn)足 gob.Encoder 和 gob. Decoder 接口,這樣會(huì)導(dǎo)致 gob 格式的 讀寫(xiě)相當(dāng)?shù)寐?,并且文件大小也?huì)膨脹。

對(duì)于可讀的數(shù)據(jù),XML 可能是最好使用的格式,特別是作為一種數(shù)據(jù)交換格式時(shí)非常有用。與處理 JSON 格式相比,處理 XML 格式需要更多行代碼。這是因?yàn)?Go [沒(méi)有一個(gè) xml.Marshaler 接口,也因?yàn)槲覀冞@里使用了并行的數(shù)據(jù)類(lèi)型 (XMLInvoice 和 XMLItem)來(lái)幫助映射 XML 數(shù)據(jù)和發(fā)票數(shù)據(jù)(invoice 和 Item)。

使用 XML 作為外部存儲(chǔ)格式的應(yīng)用程序可能不需要并行的數(shù)據(jù)類(lèi)型或者也不需要 invoicedata 程序這樣的 轉(zhuǎn)換,因此就有可能比 invoicedata 例子中所給出的更快,并且所需的代碼也更少。

除了讀寫(xiě)速度和文件大小以及代碼行數(shù)之外,還有另一個(gè)問(wèn)題值得考慮:格式的穩(wěn)健性。例如,如果我們?yōu)?Invoice 結(jié)構(gòu)體和 Item 結(jié)構(gòu)體添加了一個(gè)字段,那么就必須再改變文件的格式。我們的代碼適應(yīng)讀寫(xiě)新格式并繼續(xù)支持讀舊格式的難易程度如何?如果我們?yōu)槲募袷蕉x版本,這樣的變化就很容易被適應(yīng)(會(huì)以本章一個(gè)練習(xí)的形式給岀),除了讓 JSON 格式同時(shí)適應(yīng)讀寫(xiě)新舊格式稍微復(fù)雜一點(diǎn)之外。

除了 Invoice 和 Item 結(jié)構(gòu)體之外,所有文件格式都共享以下常量:

const (
    fileType        = "INVOICES"        //用于純文本格式
    magicNumber     = 0xl25D            // 用于二進(jìn)制格式
    fileVersion     = 100               //用于所有的格式
    dataFormat      = "2006-01-02"      //必須總是使用該日期
)

magicNumber 用于唯一標(biāo)記發(fā)票文件。fileVersion 用于標(biāo)記發(fā)票文件的版本,該標(biāo)記便于之后修改程序來(lái)適應(yīng)數(shù)據(jù)格式的改變。dataFormat 稍后介紹,它表 示我們希望數(shù)據(jù)如何按照可讀的格式進(jìn)行格式化。

同時(shí),我們也創(chuàng)建了一對(duì)接口。

type InvoiceMarshaler interface {
    Marshallnvoices(writer io.Writer, invoices []*Invoice) error
}
type InvoiceUnmarshaler interface {
    Unmarshallnvoices(reader io.Reader) ([]*Invoice, error)
}

這樣做的目的是以統(tǒng)一的方式針對(duì)特定格式使用 reader 和 writer。例如,下列函數(shù)是 invoicedata 程序用來(lái)從一個(gè)打開(kāi)的文件中讀取發(fā)票數(shù)據(jù)的。

func readinvoices(reader io.Reader, suffix string)([]*Invoice, error) {
    var unmarshaler InvoicesUnmarshaler
    switch suffix {
        case ".gobn:
            unmarshaler = GobMarshaler{}
        case H.inv":
            unmarshaler = InvMarshaler{}
        case ,f. jsn", H. jsonn:
            unmarshaler = JSONMarshaler{}
        case ".txt”:
            unmarshaler = TxtMarshaler{}
        case ".xml":
            unmarshaler = XMLMarshaler{}
    }
    if unmarshaler != nil {
        return unmarshaler.Unmarshallnvoices(reader)
    }
    return nil, fmt.Errorf("unrecognized input suffix: %s", suffix)
}

其中,reader 是任何能夠滿(mǎn)足 io.Reader 接口的值,例如,一個(gè)打開(kāi)的文件 ( 其類(lèi)型為 *os . File)> 一個(gè) gzip 解碼器 ( 其類(lèi)型為 *gzip. Reader) 或者一個(gè) string. Readero 字符串 suffix 是文件的后綴名 ( 從 .gz 文件中解壓之后)。

在接下來(lái)的小節(jié)中我們將會(huì)看到 GobMarshaler 和 InvMarshaler 等自定義的類(lèi)型,它們提供了 MarshmlTnvoices() 和 Unmarshallnvoices() 方法 (因此滿(mǎn)足 InvoicesMarshaler 和 InvoicesUnmarshaler 接口)。


文章名稱(chēng):創(chuàng)新互聯(lián)GO教程:Go語(yǔ)言自定義數(shù)據(jù)文件
文章轉(zhuǎn)載:http://www.5511xx.com/article/dposohh.html