亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何使用Golang創(chuàng)建與讀取Excel文件

 更新時間:2022年07月08日 08:21:58   作者:飛書技術(shù)  
我最近工作忙于作圖,圖表,需要自己準備數(shù)據(jù)源,所以經(jīng)常和Excel打交道,下面這篇文章主要給大家介紹了關(guān)于如何使用Golang創(chuàng)建與讀取Excel文件的相關(guān)資料,需要的朋友可以參考下

摘要

本文提出一種使用 Golang 進行 Excel 文件創(chuàng)建和讀取的方案。首先對問題進行分析,引出方案的基本架構(gòu);然后分章節(jié)描述了 Excelize 基礎(chǔ)庫的基本用法,以及 Excel 數(shù)據(jù)在 Golang 中的表示和解析方式,并進一步提出了應(yīng)對大規(guī)模數(shù)據(jù)寫入場景的優(yōu)化方法;最后,指出了一些可能遇到的問題和對策。

引言

飛書是業(yè)界領(lǐng)先的下一代企業(yè)協(xié)作與管理平臺,集合了很多細分領(lǐng)域的優(yōu)秀 ToB 產(chǎn)品。作者所在的部門,負責(zé)員工持股計劃(Employee Stock Ownership Plan,ESOP)相關(guān)系統(tǒng)的研發(fā),主要的后端開發(fā)語言為 Golang 。系統(tǒng)管理員,需要定期對公司 ESOP 的參與人信息,以及股權(quán)激勵的授予、歸屬、取消等信息,以Excel表格的形式進行匯總,為相關(guān)決策提供參考和依據(jù);必要時,也需要通過修改 Excel 數(shù)據(jù)表,上傳系統(tǒng),實現(xiàn)參與人、授予等信息的批量修改。

總而言之,隨著 Golang 的廣泛應(yīng)用,如何使用 Golang 進行 Excel 數(shù)據(jù)表的讀取和創(chuàng)建,是一個值得探討的問題。本文將描述一套完整的 Excel 文件創(chuàng)建和讀取的方案,方案力圖做到靈活通用,和具體的業(yè)務(wù)數(shù)據(jù)類型無關(guān),同時能夠兼顧大規(guī)模數(shù)據(jù)導(dǎo)出的效率。最后,分享了一些研發(fā)過程中遇到的問題,希望能夠避免讀者再次踩坑。

正文

架構(gòu)

在開始具體深入地描述我們的方案之前,不妨先思考一下,實現(xiàn)這樣一個方案,需要解決的問題都有哪些?數(shù)據(jù)的處理大致應(yīng)該是一個什么樣的流程?下圖是ESOP系統(tǒng)中,涉及到Excel文件創(chuàng)建和讀取的部分業(yè)務(wù)場景。

文件對象

很自然地,我們需要引入一個 Excel 文件對象,此對象應(yīng)該包含一個 Excel 工作簿的所有信息:有哪些工作表,每個工作表都有哪些列,每一行數(shù)據(jù)是什么,單元格和文本的格式是什么樣的,某一列是否包含枚舉值,等等。我們對文件的任何操作,無論是數(shù)據(jù)的增刪改,還是格式樣式的變更,亦或是文件的打開和保存,都應(yīng)該將這個文件對象作為切入點。

數(shù)據(jù)的表示

一個 Excel 工作表,可以很自然地和 Golang 結(jié)構(gòu)體聯(lián)系起來,工作表的每一列對應(yīng)結(jié)構(gòu)體中的一個字段。然而,只定義一個基本的結(jié)構(gòu)體還不夠,至少還應(yīng)該想辦法保存每個字段對應(yīng)的 Excel 列名、數(shù)據(jù)驗證等等。

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

用 Golang 結(jié)構(gòu)體表示了一個 Excel 工作表,自然還需要一種方法來解釋結(jié)構(gòu)體中記錄的各種 Excel 數(shù)據(jù)信息,這樣,程序代碼才知道如何將結(jié)構(gòu)體數(shù)據(jù)正確地寫入文件對象,以及反過來,如何讀取文件對象中的數(shù)據(jù),來還原 Golang 結(jié)構(gòu)體。數(shù)據(jù)表示和解析的整體思路,如下圖所示。

實際架構(gòu)

幸運的是,上面幾個問題,我們都可以找到成熟且有力的工具來解決。方案基本的架構(gòu)如下圖所示。

文件對象的創(chuàng)建和各種操作,我們通過 Excelize 基礎(chǔ)庫來實現(xiàn),后面會對該基礎(chǔ)庫進行簡要介紹。

Excel 數(shù)據(jù)的表示,我們使用包含 tag 的 Golang 結(jié)構(gòu)體實現(xiàn),數(shù)據(jù)值以外的其他信息,用某種格式記錄在 tag 中。

Excel 數(shù)據(jù)的解析,我們利用 Golang 的反射機制實現(xiàn)。通過反射,我們可以解析出結(jié)構(gòu)體每個字段的值以及 tag 中保存的其他有用信息。

Excelize 基礎(chǔ)庫

Excelize 是一個使用 Golang 編寫的,用于操作 Office Excel 文檔的基礎(chǔ)庫,支持 Golang 1.15 及以上版本。下面對其基本用法進行介紹,涉及到的各 API 的具體用法,可查看文章末尾給出的Excelize Doc鏈接。

文件

文件對象是本文大部分 Excel 文件操作的入口。使用 NewFile 函數(shù),可以創(chuàng)建一個空白的文件對象。如果需要用已有的 Excel 文件數(shù)據(jù)創(chuàng)建文件對象,可以使用 OpenReader 或者 OpenFile 函數(shù)。結(jié)束文件操作之后,通常需要將文件保存在本地,或者將文件輸出為字節(jié)數(shù)組,返回給前端供用戶下載,使用文件對象的 SaveAs 和 WriteToBuffer 方法,可以達到目的。

坐標

在使用更多功能之前,必須搞清楚如何定位一個單元格或一個區(qū)域。

Excel 中使用形如“A1”這樣的坐標來定位單元格。相應(yīng)的,在 Excelize 基礎(chǔ)庫中,可以通過 CoordinatesToCellName 函數(shù),將行號和列號這個二元組,轉(zhuǎn)換為一個形如“A1”的坐標。一些操作,需要通過兩個坐標來確定生效區(qū)域,此時,兩個相同的坐標表示對一個單元格生效,兩個不同的坐標表示對一個矩形區(qū)域生效,分別指向區(qū)域左上角和右下角的單元格。

樣式

樣式包含字體、文字大小、粗細、位置、顏色等屬性。Excelize 中,樣式可以通過 NewStyle 方法創(chuàng)建,返回一個整數(shù)索引,唯一標識這個樣式。通過文件對象的 SetCellStyle 方法,指定坐標和樣式索引,可以為一個區(qū)域設(shè)置統(tǒng)一的樣式。

單元格操作

單元格的常用操作有設(shè)置高度和寬度、合并單元格、設(shè)置單元格數(shù)據(jù)等。

我們針對一行設(shè)置高度,針對一列設(shè)置寬度,分別使用文件對象中的 SetRowHeight 和 SetColWidth 方法進行。

在“坐標”部分,我們講解了如何確定一個區(qū)域,合并單元格的操作,就是一個例子,我們可以使用文件對象中的 MergeCell 方法來完成。

一般情況下,數(shù)據(jù)的寫入操作,在單元格層面進行。使用文件對象中的 SetCellValue 方法,指定一個坐標,可以將 Golang 中常用的數(shù)據(jù)類型(包括無符號整數(shù)、有符號整數(shù)、浮點數(shù)、字節(jié)切片、字符串、時間、布爾類型等等)的值寫入對應(yīng)的單元格。

數(shù)據(jù)驗證

數(shù)據(jù)驗證功能,可以為某一列數(shù)據(jù)定義枚舉值,用戶可以使用下拉列表,為該列中某一行選擇要填入的值。

使用 NewDataValidation 函數(shù),可以創(chuàng)建一個數(shù)據(jù)驗證對象,不妨命名為 vd 。為了指定 vd 的生效范圍,需要為 vd 設(shè)置一個 Sqref 屬性,格式形如“A1:A10”,表示此 vd 對第 1 列中第 1 行到第 10 行的數(shù)據(jù)生效。然后,使用 vd 的 SetDropList 方法,設(shè)置下拉列表的內(nèi)容。最后,使用文件對象中的 AddDataValidation 方法,將此 vd 寫入文件。

數(shù)據(jù)的表示和解析

表示

根據(jù)“架構(gòu)”部分的設(shè)想,我們可以定義一個帶有 tag 的結(jié)構(gòu)體,來表示一個 Excel 工作表。

Golang 結(jié)構(gòu)體的 tag ,是以鍵值對的形式表示的。為了和其他用途的 tag 進行區(qū)分,我們將本方案的 tag 信息,用一個名為 ex 的鍵來表示,而 ex 的值,仍然沿用鍵值對的形式,如下列代碼所示:

type PeopleInfo struct {
    PeopleNo          string `ex:"head:工號;type:string;required;color:#0070C0"`
    PeopleName        string `ex:"head:姓名;type:string;required"`
    BirthDate         string `ex:"head:出生日期;type:date;omitempty"`
    EmploymentStatus  string `ex:"head:在職狀態(tài);type:string;select:在職,離職"`
}

我們可以為ex設(shè)計下列屬性:

  • head,指定了此結(jié)構(gòu)體字段對應(yīng)的 Excel 列名。
  • type,表示在使用反射進行數(shù)據(jù)解析時,會將此結(jié)構(gòu)體字段的值作為指定的類型處理。
  • select,表示此字段所在的列,包含一個下拉列表,列表中的枚舉值由 select 后面的值指定。
  • required,表示此字段必須包含非零值,否則在寫入 Excel 時會報錯。
  • omitempty,表示此字段如果是零值,則對應(yīng)的單元格留空。
  • color,指定了列名所在單元格的顏色,通過這個字段,可以為不同的列名設(shè)置不同的底色,賦予一些含義,例如,可以將必填的列和選填的列,設(shè)置不同的底色??梢酝ㄟ^ Excel 的 RGB 顏色設(shè)置窗口,查看不同顏色對應(yīng)的色號,作為 color 屬性的值。

此外,我們還要定義一個結(jié)構(gòu)體,保存 ex 的解析結(jié)果,結(jié)構(gòu)體不妨命名為 Setting :

type Setting struct {
    Head      string
    Type      string
    Select    []string
    Required  bool
    OmitEmpty bool
    Color     string
}

解析

使用 Golang 的反射機制,對類似于 PeopleInfo 這樣的結(jié)構(gòu)體,我們可以抽取每個字段的ex值,進行字符串處理后,組裝成Setting對象。示例代碼如下:

import reflect

// 解析第idx個字段的ex
func ParseEx(idx int, data interface{}) *Setting {
    tp := reflect.ValueOf(data).Type().Elem().Elem() // 獲得結(jié)構(gòu)體的反射Type
    field := tp.Field(idx)
    exStr := field.Tag.Get("ex") // 獲得tag中ex的值
    setting := &Setting{}
    // 下面可通過對exStr字符串進行切分,來組裝Setting對象,較為簡單,省略
    ...
    return setting
}

func main() {
    ParseEx(0, []*PeopleInfo{{}})
}

由于反射機制較為抽象,這里不再贅述,對反射不熟悉的讀者,可以查看文章末尾給出的 Golang reflect 鏈接。

組裝了 Setting 之后,我們可以繼續(xù)通過反射,來獲取結(jié)構(gòu)體中各字段的值,然后使用前面介紹過的一些 API ,將這些信息寫入 Excel 文件。

下面給出創(chuàng)建 Excel 文件的示例代碼,代碼對 omitempty 和 type 屬性進行了處理,并將部分數(shù)據(jù)寫入文件對象。其他 ex 屬性的處理,因篇幅有限,不再演示,讀者有興趣可以自己嘗試實現(xiàn)。

import reflect

import "github.com/xuri/excelize/v2"

// 寫入第1行數(shù)據(jù)的第idx個字段
func WriteFirstRow(ef *excelize.File, idx int, data interface{}) error {
    firstRow := reflect.ValueOf(data).Index(0).Elem() // 第1個數(shù)據(jù)的反射Value
    v := firstRow.Field(idx) // 第idx個字段的反射Value
    setting := ParseEx(idx, data) // 第idx個字段解析出來的ex信息
    
    // 處理omitempty
    if setting.OmitEmpty && v.IsZero() {
       return nil
    }
    
    var val interface{}
    // 處理type
    switch setting.Type {
    case "string":
        val = v.String()
    case ...
    }
    
    // Excel列號從1開始,所以列號是idx+1;行號從2開始,因為第1行要顯示列名
    axis, err := excelize.CoordinatesToCellName(idx+1, 2)
    if err != nil {
        return err
    }
    
    // 將數(shù)據(jù)寫入默認工作表Sheet1中axis坐標處的單元格
    return ef.SetCellValue("Sheet1", axis, val)
}

func main() {
    ef := excelize.NewFile()
    WriteFirstRow(ef, 0, []*PeopleInfo{{PeopleNo: "test"}})
    ef.SaveAs("people_info.xlsx")
}

上面給出的是創(chuàng)建 Excel 文件的示例。讀取 Excel 文件的過程是類似的,首先從二進制數(shù)據(jù)創(chuàng)建出文件對象,然后根據(jù)文件對象中的每一列數(shù)據(jù),生成對應(yīng)的結(jié)構(gòu)體對象。示例代碼如下。

import reflect

import "github.com/xuri/excelize/v2"

// 讀取第1行數(shù)據(jù)的第idx列,假定idx從0開始,只有一個默認工作表Sheet1,數(shù)據(jù)從第2行開始
func ReadFirstRow(ef *excelize.File, idx int, holder interface{}) error {
    rows, err := ef.GetRows("Sheet1") // 所有行
    if err != nil {
       return err
    }
    row := rows[1]

    tp := reflect.TypeOf(holder).Elem().Elem().Elem() // 結(jié)構(gòu)體的類型
    val := reflect.New(tp)                            // 創(chuàng)建一個新的結(jié)構(gòu)體對象

    field := val.Elem().Field(idx) // 第idx個字段的反射Value
    cellValue := row[idx]          // 第idx個字段對應(yīng)的Excel數(shù)據(jù)
    field.SetString(cellValue)     // 將Excel數(shù)據(jù)保存到結(jié)構(gòu)體對象的對應(yīng)字段中

    listV := reflect.ValueOf(holder)
    listV.Elem().Set(reflect.Append(listV.Elem(), val)) // 將結(jié)構(gòu)體對象添加到holder中

    return nil
}

func main() {
    ef, _ := excelize.OpenFile("people_info.xlsx")
    holder := make([]*PeopleInfo, 0, 10)
    ReadFirstRow(ef, 0, &holder)
}

本節(jié)描述了如何使用 Golang 來表示和解析 Excel 數(shù)據(jù),以及在此基礎(chǔ)上如何創(chuàng)建和讀取 Excel 文件。示例代碼中對 Excel 文件的寫入和讀取操作函數(shù),使用 interface 類型的參數(shù)作為數(shù)據(jù)提供方或接收方,和具體的業(yè)務(wù)數(shù)據(jù)類型無關(guān),因此該方案具備通用性。

大規(guī)模數(shù)據(jù)的寫入

之前演示的 Excel 文件寫入方式,是在單元格層面進行的,在大規(guī)模數(shù)據(jù)寫入的場景下,耗時長,體驗差。Excelize 提供了一套流式寫入 API,以行為單位寫入 Excel 數(shù)據(jù),能夠顯著提高大規(guī)模數(shù)據(jù)的寫入效率。

使用流式 API 寫入 Excel 數(shù)據(jù),首先需要使用文件對象的 NewStreamWriter 方法,創(chuàng)建一個流式寫入器。寫入一行數(shù)據(jù)時,需要構(gòu)造一個切片,表示這一行數(shù)據(jù),切片中每個元素表示一個單元格信息,包含單元格的值和樣式。單元格元素,可以使用 Excelize 中提供的 Cell 數(shù)據(jù)類型來表示。之后,就可以通過流式寫入器的 SetRow 方法,將行數(shù)據(jù)寫入 Excel 文件。行的高度,可以在寫入時指定。示例代碼如下:

import reflect

import "github.com/xuri/excelize/v2"

// 寫入第1行數(shù)據(jù)
func StreamWriteFirstRow(sw *excelize.StreamWriter, data interface{}) error {
    firstRow := reflect.ValueOf(data).Index(0).Elem() // 第1個數(shù)據(jù)的反射Value
    v := firstRow.Field(0) // 首個字段的反射Value
    style := &excelize.Style{
        Alignment: &excelize.Alignment{
            Horizontal: "left",
            Vertical:   "center",
        },
    }
    styleID, err := sw.File.NewStyle(style) // 創(chuàng)建樣式
    if err != nil {
        return err
    }
    
    length := firstRow.NumField() // 結(jié)構(gòu)體字段數(shù)量
    
    row := make([]interface{}, length) // 創(chuàng)建一個切片,表示一行數(shù)據(jù)
    row[0] = excelize.Cell{
       Value: v.String(),
       StyleID: styleID,
    } // 這里只寫入首個字段
    
    // 每一行都是從列號1開始;行號從2開始,因為假定第1行要顯示列名
    axis, err := excelize.CoordinatesToCellName(1, 2)
    if err != nil {
        return err
    }
    
    // 流式寫入行,并指定高度
    return sw.SetRow(axis, row, excelize.RowOpts{Height: 16})
}

func main() {
    ef := excelize.NewFile()
    sw, _ := ef.NewStreamWriter("Sheet1")
    StreamWriteFirstRow(sw, []*PeopleInfo{{PeopleNo: "test"}})
    sw.Flush()
    ef.SaveAs("stream_people_info.xlsx")
}

需要關(guān)注的問題

大量枚舉值的設(shè)置

在“數(shù)據(jù)驗證”部分,我們提到使用 SetDropList 方法可以設(shè)置下拉列表。然而,這樣設(shè)置的下拉列表是有局限性的:每個枚舉值使用逗號拼接后得到的字符串,其總長度不得超過 255 個字符。

如果超過了這個限制,我們需要創(chuàng)建一個工作表(假設(shè)名稱為 enum ),將枚舉值存儲在 enum 工作表的某一列中(假設(shè)存儲在 A 列,第 2 行到第 10 行),然后通過 vd 的 SetSqrefDropList 方法設(shè)置下拉列表,此方法通過一個形如“enum!A2:A10”的字符串來指定枚舉值的存儲位置,即 enum 工作表 A 列的第 2 行到第 10 行。

大工作表的讀取

讀取 Excel 文件時,我們會基于已有的物理文件來創(chuàng)建文件對象,如果其中有一個很大的工作表,那么當(dāng)我們將這個文件對象另存為一個新的物理文件時,可能會發(fā)現(xiàn)文件變小了,且無法正常打開。

Excelize 庫通過一些參數(shù),來限制打開和讀取工作薄時的內(nèi)存使用。其中,WorksheetUnzipMemLimit 參數(shù)限制了 unzip 一個工作表時允許使用的最大內(nèi)存,默認為 16 MB 。當(dāng)一個工作表大小超過這一默認值時,此工作表的數(shù)據(jù)會 unzip 到操作系統(tǒng)的臨時文件中。然而,當(dāng)我們進行另存為操作時,這些臨時文件的數(shù)據(jù)卻被 Excelize 的相關(guān)函數(shù)忽略了。

這可能是 Excelize 庫的一個 bug ,但是我們可以通過增大 WorksheetUnzipMemLimit 參數(shù)來規(guī)避。這一參數(shù)的值,可根據(jù)具體業(yè)務(wù)場景來設(shè)置,最大可以設(shè)置為和 UnzipSizeLimit 參數(shù)相同,后者是打開整個工作簿時總的內(nèi)存使用限制,默認為 16 GB 。

流式寫入的注意事項

流式操作有自己的一套 API ,用于數(shù)據(jù)寫入、合并單元格、設(shè)置列寬等操作。流式 API 不能和普通的非流式 API 混用,否則可能無法正確寫入數(shù)據(jù)或設(shè)置格式。使用流式 API 設(shè)置列寬,需要在寫入數(shù)據(jù)之前進行。流式寫入完成之后,需要調(diào)用流式寫入器的 Flush 方法來結(jié)束寫入,否則保存文件時可能會丟失數(shù)據(jù)。

結(jié)語

本文對 Golang 中創(chuàng)建和讀取 Excel 文件所涉及的各方面問題,進行了總結(jié)歸納,并提出了一套完整的方案。此方案使用 Golang 結(jié)構(gòu)體的 tag ,以及 Golang 反射機制,對 Excel 數(shù)據(jù)進行定義和解釋,實現(xiàn)了 Golang 結(jié)構(gòu)體和 Excel 數(shù)據(jù)的雙向映射,同時使用成熟強大的 Excelize 基礎(chǔ)庫,對 Excel 文件進行創(chuàng)建、寫入、讀取等操作。

希望讀者能有所收獲,為解決實際的問題提供思路,也歡迎大家對方案中的不足之處提出改進意見。

參考資料

總結(jié)

到此這篇關(guān)于如何使用Golang創(chuàng)建與讀取Excel文件的文章就介紹到這了,更多相關(guān)Golang創(chuàng)建讀取Excel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang中beego入門

    golang中beego入門

    Beego是一個基于Go語言的開源框架,用于構(gòu)建Web應(yīng)用程序和API,本文主要介紹了golang中beego入門,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • go如何刪除字符串中的部分字符

    go如何刪除字符串中的部分字符

    這篇文章主要介紹了go刪除字符串中的部分字符操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go接口構(gòu)建可擴展Go應(yīng)用示例詳解

    Go接口構(gòu)建可擴展Go應(yīng)用示例詳解

    本文深入探討了Go語言中接口的概念和實際應(yīng)用場景。從基礎(chǔ)知識如接口的定義和實現(xiàn),到更復(fù)雜的實戰(zhàn)應(yīng)用如解耦與抽象、多態(tài)、錯誤處理、插件架構(gòu)以及資源管理,文章通過豐富的代碼示例和詳細的解釋,展示了Go接口在軟件開發(fā)中的強大功能和靈活性
    2023-10-10
  • go語言如何導(dǎo)入和使用包示例詳解

    go語言如何導(dǎo)入和使用包示例詳解

    這篇文章主要為大家介紹了go語言如何導(dǎo)入和使用包示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • Golang中的[]byte與16進制(String)之間的轉(zhuǎn)換方式

    Golang中的[]byte與16進制(String)之間的轉(zhuǎn)換方式

    這篇文章主要介紹了Golang中的[]byte與16進制(String)之間的轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Go語言{}大括號的特殊用法實例探究

    Go語言{}大括號的特殊用法實例探究

    這篇文章主要為大家介紹了Go語言{}大括號的特殊用法實例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • golang如何用type-switch判斷interface變量的實際存儲類型

    golang如何用type-switch判斷interface變量的實際存儲類型

    這篇文章主要介紹了golang如何用type-switch判斷interface變量的實際存儲類型,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • golang基于websocket通信tcp keepalive研究記錄

    golang基于websocket通信tcp keepalive研究記錄

    這篇文章主要為大家介紹了golang基于websocket通信tcp keepalive研究記錄,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Go到底能不能實現(xiàn)安全的雙檢鎖(推薦)

    Go到底能不能實現(xiàn)安全的雙檢鎖(推薦)

    這篇文章主要介紹了Go到底能不能實現(xiàn)安全的雙檢鎖,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • 詳解Go語言中init的使用與常見應(yīng)用場景

    詳解Go語言中init的使用與常見應(yīng)用場景

    Go?中有一個特別的?init()?函數(shù),它主要用于包的初始化,這篇文章將以此為主題介紹?Go?中?init()?函數(shù)的使用和常見使用場景,希望對大家有所幫助
    2024-02-02

最新評論