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

Golang性能提升利器之SectionReader的用法詳解

 更新時(shí)間:2023年07月03日 08:12:26   作者:starrySky  
本文將介紹 Go 語(yǔ)言中的 SectionReader,包括 SectionReader的基本使用方法、實(shí)現(xiàn)原理、使用注意事項(xiàng),感興趣的小伙伴可以了解一下

一. 簡(jiǎn)介

本文將介紹 Go 語(yǔ)言中的 SectionReader,包括 SectionReader的基本使用方法、實(shí)現(xiàn)原理、使用注意事項(xiàng)。從而能夠在合適的場(chǎng)景下,更好得使用SectionReader類型,提升程序的性能。

二. 問(wèn)題引入

這里我們需要實(shí)現(xiàn)一個(gè)基本的HTTP文件服務(wù)器功能,可以處理客戶端的HTTP請(qǐng)求來(lái)讀取指定文件,并根據(jù)請(qǐng)求的Range頭部字段返回文件的部分?jǐn)?shù)據(jù)或整個(gè)文件數(shù)據(jù)。

這里一個(gè)簡(jiǎn)單的思路,可以先把整個(gè)文件的數(shù)據(jù)加載到內(nèi)存中,然后再根據(jù)請(qǐng)求指定的范圍,截取對(duì)應(yīng)的數(shù)據(jù)返回回去即可。下面提供一個(gè)代碼示例:

func serveFile(w http.ResponseWriter, r *http.Request, filePath string) {
    // 打開(kāi)文件
    file, _ := os.Open(filePath)
    defer file.Close()
    // 讀取整個(gè)文件數(shù)據(jù)
    fileData, err := ioutil.ReadAll(file)
    if err != nil {
        // 錯(cuò)誤處理
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    // 根據(jù)Range頭部字段解析請(qǐng)求的范圍
    rangeHeader := r.Header.Get("Range")
    ranges, err := parseRangeHeader(rangeHeader)
    if err != nil {
        // 錯(cuò)誤處理
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    // 處理每個(gè)范圍并返回?cái)?shù)據(jù)
    for _, rng := range ranges {
        start := rng.Start
        end := rng.End
        // 從文件數(shù)據(jù)中提取范圍的字節(jié)數(shù)據(jù)
        rangeData := fileData[start : end+1]
        // 將范圍數(shù)據(jù)寫入響應(yīng)
        w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, fileInfo.Size()))
        w.Header().Set("Content-Length", strconv.Itoa(len(rangeData)))
        w.WriteHeader(http.StatusPartialContent)
        w.Write(rangeData)
    }
}
type Range struct {
    Start int
    End   int
}
// 解析HTTP Range請(qǐng)求頭
func parseRangeHeader(rangeHeader string) ([]Range, error){}

上述的代碼實(shí)現(xiàn)比較簡(jiǎn)單,首先,函數(shù)打開(kāi)filePath指定的文件,使用ioutil.ReadAll函數(shù)讀取整個(gè)文件的數(shù)據(jù)到fileData中。接下來(lái),從HTTP請(qǐng)求頭中Range頭部字段中獲取范圍信息,獲取每個(gè)范圍請(qǐng)求的起始和終止位置。接著,函數(shù)遍歷每一個(gè)范圍信息,提取文件數(shù)據(jù)fileData 中對(duì)應(yīng)范圍的字節(jié)數(shù)據(jù)到rangeData中,然后將數(shù)據(jù)返回回去?;诖?,簡(jiǎn)單實(shí)現(xiàn)了一個(gè)支持范圍請(qǐng)求的HTTP文件服務(wù)器。

但是當(dāng)前實(shí)現(xiàn)其實(shí)存在一個(gè)問(wèn)題,即在每次請(qǐng)求都會(huì)將整個(gè)文件加載到內(nèi)存中,即使用戶只需要讀取其中一小部分?jǐn)?shù)據(jù),這種處理方式會(huì)給內(nèi)存帶來(lái)非常大的壓力。假如被請(qǐng)求文件的大小是100M,一個(gè)32G內(nèi)存的機(jī)器,此時(shí)最多只能支持320個(gè)并發(fā)請(qǐng)求。但是用戶每次請(qǐng)求可能只是讀取文件的一小部分?jǐn)?shù)據(jù),比如1M,此時(shí)將整個(gè)文件加載到內(nèi)存中,往往是一種資源的浪費(fèi),同時(shí)從磁盤中讀取全部數(shù)據(jù)到內(nèi)存中,此時(shí)性能也較低。

那能不能在處理請(qǐng)求時(shí),HTTP文件服務(wù)器只讀取請(qǐng)求的那部分?jǐn)?shù)據(jù),而不是加載整個(gè)文件的內(nèi)容,go基礎(chǔ)庫(kù)有對(duì)應(yīng)類型的支持嗎?

其實(shí)還真有,Go語(yǔ)言中其實(shí)存在一個(gè)SectionReader的類型,它可以從一個(gè)給定的數(shù)據(jù)源中讀取數(shù)據(jù)的特定片段,而不是讀取整個(gè)數(shù)據(jù)源,這個(gè)類型在這個(gè)場(chǎng)景下使用非常合適。

下面我們先仔細(xì)介紹下SectionReader的基本使用方式,然后將其作用到上面文件服務(wù)器的實(shí)現(xiàn)當(dāng)中。

三. 基本使用

3.1 基本定義

SectionReader類型的定義如下:

type SectionReader struct {
   r     ReaderAt
   base  int64
   off   int64
   limit int64
}

SectionReader包含了四個(gè)字段:

  • r:一個(gè)實(shí)現(xiàn)了ReaderAt接口的對(duì)象,它是數(shù)據(jù)源。
  • base: 數(shù)據(jù)源的起始位置,通過(guò)設(shè)置base字段,可以調(diào)整數(shù)據(jù)源的起始位置。
  • off:讀取的起始位置,表示從數(shù)據(jù)源的哪個(gè)偏移量開(kāi)始讀取數(shù)據(jù),初始化時(shí)一般與base保持一致。
  • limit:數(shù)據(jù)讀取的結(jié)束位置,表示讀取到哪里結(jié)束。

同時(shí)還提供了一個(gè)構(gòu)造器方法,用于創(chuàng)建一個(gè)SectionReader實(shí)例,定義如下:

func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader {
   // ... 忽略一些驗(yàn)證邏輯
   // remaining 代表數(shù)據(jù)讀取的結(jié)束位置,為 base(偏移量) + n(讀取字節(jié)數(shù))
   remaining = n + off
   return &SectionReader{r, off, off, remaining}
}

NewSectionReader接收三個(gè)參數(shù),r 代表實(shí)現(xiàn)了ReadAt接口的數(shù)據(jù)源,off表示起始位置的偏移量,也就是要從哪里開(kāi)始讀取數(shù)據(jù),n代表要讀取的字節(jié)數(shù)。通過(guò)NewSectionReader函數(shù),可以很方便得創(chuàng)建出SectionReader對(duì)象,然后讀取特定范圍的數(shù)據(jù)。

3.2 使用方式

SectionReader 能夠像io.Reader一樣讀取數(shù)據(jù),唯一區(qū)別是會(huì)被限定在指定范圍內(nèi),只會(huì)返回特定范圍的數(shù)據(jù)。

下面通過(guò)一個(gè)例子來(lái)說(shuō)明SectionReader的使用,代碼示例如下:

package main
import (
        "fmt"
        "io"
        "strings"
)
func main() {
        // 一個(gè)實(shí)現(xiàn)了 ReadAt 接口的數(shù)據(jù)源
        data := strings.NewReader("Hello,World!")
        // 創(chuàng)建 SectionReader,讀取范圍為索引 2 到 9 的字節(jié)
        // off = 2, 代表從第二個(gè)字節(jié)開(kāi)始讀取; n = 7, 代表讀取7個(gè)字節(jié)
        section := io.NewSectionReader(data, 2, 7)
        // 數(shù)據(jù)讀取緩沖區(qū)長(zhǎng)度為5
        buffer := make([]byte, 5)
        for {
                // 不斷讀取數(shù)據(jù),直到返回io.EOF
                n, err := section.Read(buffer)
                if err != nil {
                        if err == io.EOF {
                                // 已經(jīng)讀取到末尾,退出循環(huán)
                                break
                        }
                        fmt.Println("Error:", err)
                        return
                }
                fmt.Printf("Read %d bytes: %s\n", n, buffer[:n])
        }
}

上述函數(shù)使用 io.NewSectionReader 創(chuàng)建了一個(gè) SectionReader,指定了開(kāi)始讀取偏移量為 2,讀取字節(jié)數(shù)為 7。這意味著我們將從第三個(gè)字節(jié)(索引 2)開(kāi)始讀取,讀取 7 個(gè)字節(jié)。

然后我們通過(guò)一個(gè)無(wú)限循環(huán),不斷調(diào)用Read方法讀取數(shù)據(jù),直到讀取完所有的數(shù)據(jù)。函數(shù)運(yùn)行結(jié)果如下,確實(shí)只讀取了范圍為索引 2 到 9 的字節(jié)的內(nèi)容:

Read 5 bytes: llo,W
Read 2 bytes: or

因此,如果我們只需要讀取數(shù)據(jù)源的某一部分?jǐn)?shù)據(jù),此時(shí)可以創(chuàng)建一個(gè)SectionReader實(shí)例,定義好數(shù)據(jù)讀取的偏移量和數(shù)據(jù)量之后,之后可以像普通的io.Reader那樣讀取數(shù)據(jù),SectionReader確保只會(huì)讀取到指定范圍的數(shù)據(jù)。

3.3 使用例子

這里回到上面HTTP文件服務(wù)器實(shí)現(xiàn)的例子,之前的實(shí)現(xiàn)存在一個(gè)問(wèn)題,即每次請(qǐng)求都會(huì)讀取整個(gè)文件的內(nèi)容,這會(huì)代碼內(nèi)存資源的浪費(fèi),性能低,響應(yīng)時(shí)間比較長(zhǎng)等問(wèn)題。下面我們使用SectionReader 對(duì)其進(jìn)行優(yōu)化,實(shí)現(xiàn)如下:

func serveFile(w http.ResponseWriter, r *http.Request, filePath string) {
        // 打開(kāi)文件
        file, err := os.Open(filePath)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
        }
        defer file.Close()
        // 獲取文件信息
        fileInfo, err := file.Stat()
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
        }
        // 根據(jù)Range頭部字段解析請(qǐng)求的范圍
        rangeHeader := r.Header.Get("Range")
        ranges, err := parseRangeHeader(rangeHeader)
        if err != nil {
                http.Error(w, err.Error(), http.StatusBadRequest)
                return
        }
        // 處理每個(gè)范圍并返回?cái)?shù)據(jù)
        for _, rng := range ranges {
                start := rng.Start
                end := rng.End
                // 根據(jù)范圍創(chuàng)建SectionReader
                section := io.NewSectionReader(file, int64(start), int64(end-start+1))
                // 將范圍數(shù)據(jù)寫入響應(yīng)
                w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, fileInfo.Size()))
                w.WriteHeader(http.StatusPartialContent)
                io.CopyN(w, section, section.Size())
        }
}
type Range struct {
        Start int
        End   int
}
// 解析HTTP Range請(qǐng)求頭
func parseRangeHeader(rangeHeader string) ([]Range, error) {}

在上述優(yōu)化后的實(shí)現(xiàn)中,我們使用 io.NewSectionReader 創(chuàng)建了 SectionReader,它的范圍是根據(jù)請(qǐng)求頭中的范圍信息計(jì)算得出的。然后,我們通過(guò) io.CopyNSectionReader 中的數(shù)據(jù)直接拷貝到響應(yīng)的 http.ResponseWriter 中。

上述兩個(gè)HTTP文件服務(wù)器實(shí)現(xiàn)的區(qū)別,只在于讀取特定范圍數(shù)據(jù)方式,前一種方式是將整個(gè)文件加載到內(nèi)存中,再截取特定范圍的數(shù)據(jù);而后者則是通過(guò)使用 SectionReader,我們避免了一次性讀取整個(gè)文件數(shù)據(jù),并且只讀取請(qǐng)求范圍內(nèi)的數(shù)據(jù)。這種優(yōu)化能夠更高效地處理大文件或處理大量并發(fā)請(qǐng)求的場(chǎng)景,節(jié)省了內(nèi)存和處理時(shí)間。

四. 實(shí)現(xiàn)原理

4.1 設(shè)計(jì)初衷

SectionReader的設(shè)計(jì)初衷,在于提供一種簡(jiǎn)潔,靈活的方式來(lái)讀取數(shù)據(jù)源的特定部分。

4.2 基本原理

SectionReader 結(jié)構(gòu)體中off,baselimit字段是實(shí)現(xiàn)只讀取數(shù)據(jù)源特定部分?jǐn)?shù)據(jù)功能的重要變量。

type SectionReader struct {
   r     ReaderAt
   base  int64
   off   int64
   limit int64
}

由于SectionReader需要保證只讀取特定范圍的數(shù)據(jù),故需要保存開(kāi)始位置和結(jié)束位置的值。這里是通過(guò)baselimit這兩個(gè)字段來(lái)實(shí)現(xiàn)的,base記錄了數(shù)據(jù)讀取的開(kāi)始位置,limit記錄了數(shù)據(jù)讀取的結(jié)束位置。

通過(guò)設(shè)定baselimit兩個(gè)字段的值,限制了能夠被讀取數(shù)據(jù)的范圍。之后需要開(kāi)始讀取數(shù)據(jù),有可能這部分待讀取的數(shù)據(jù)不會(huì)被一次性讀完,此時(shí)便需要一個(gè)字段來(lái)說(shuō)明接下來(lái)要從哪一個(gè)字節(jié)繼續(xù)讀取下去,因此SectionReader也設(shè)置了off字段的值,這個(gè)代表著下一個(gè)帶讀取數(shù)據(jù)的位置。

在使用SectionReader讀取數(shù)據(jù)的過(guò)程中,通過(guò)baselimit限制了讀取數(shù)據(jù)的范圍,off則不斷修改,指向下一個(gè)帶讀取的字節(jié)。

4.3 代碼實(shí)現(xiàn)

4.3.1 Read方法說(shuō)明

func (s *SectionReader) Read(p []byte) (n int, err error) {
    // s.off: 將被讀取數(shù)據(jù)的下標(biāo)
    // s.limit: 指定讀取范圍的最后一個(gè)字節(jié),這里應(yīng)該保證s.base <= s.off
   if s.off >= s.limit {
      return 0, EOF
   }
   // s.limit - s.off: 還剩下多少數(shù)據(jù)未被讀取
   if max := s.limit - s.off; int64(len(p)) > max {
      p = p[0:max]
   }
   // 調(diào)用 ReadAt 方法讀取數(shù)據(jù)
   n, err = s.r.ReadAt(p, s.off)
   // 指向下一個(gè)待被讀取的字節(jié)
   s.off += int64(n)
   return
}

SectionReader實(shí)現(xiàn)了Read 方法,通過(guò)該方法能夠?qū)崿F(xiàn)指定范圍數(shù)據(jù)的讀取,在內(nèi)部實(shí)現(xiàn)中,通過(guò)兩個(gè)限制來(lái)保證只會(huì)讀取到指定范圍的數(shù)據(jù),具體限制如下:

  • 通過(guò)保證 off 不大于 limit 字段的值,保證不會(huì)讀取超過(guò)指定范圍的數(shù)據(jù)
  • 在調(diào)用ReadAt方法時(shí),保證傳入切片長(zhǎng)度不大于剩余可讀數(shù)據(jù)長(zhǎng)度

通過(guò)這兩個(gè)限制,保證了用戶只要設(shè)定好了數(shù)據(jù)開(kāi)始讀取偏移量 base 和 數(shù)據(jù)讀取結(jié)束偏移量 limit字段值,Read方法便只會(huì)讀取這個(gè)范圍的數(shù)據(jù)。

4.3.2 ReadAt 方法說(shuō)明

func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) {
    // off: 參數(shù)指定了偏移字節(jié)數(shù),為一個(gè)相對(duì)數(shù)值
    // s.limit - s.base >= off: 保證不會(huì)越界
   if off < 0 || off >= s.limit-s.base {
      return 0, EOF
   }
   // off + base: 獲取絕對(duì)的偏移量
   off += s.base
   // 確保傳入字節(jié)數(shù)組長(zhǎng)度 不超過(guò) 剩余讀取數(shù)據(jù)范圍
   if max := s.limit - off; int64(len(p)) > max {
      p = p[0:max]
      // 調(diào)用ReadAt 方法讀取數(shù)據(jù)
      n, err = s.r.ReadAt(p, off)
      if err == nil {
         err = EOF
      }
      return n, err
   }
   return s.r.ReadAt(p, off)
}

SectionReader還提供了ReadAt方法,能夠指定偏移量處實(shí)現(xiàn)數(shù)據(jù)讀取。它根據(jù)傳入的偏移量off字段的值,計(jì)算出實(shí)際的偏移量,并調(diào)用底層源的ReadAt方法進(jìn)行讀取操作,在這個(gè)過(guò)程中,也保證了讀取數(shù)據(jù)范圍不會(huì)超過(guò)baselimit字段指定的數(shù)據(jù)范圍。

這個(gè)方法提供了一種靈活的方式,能夠在限定的數(shù)據(jù)范圍內(nèi),隨意指定偏移量來(lái)讀取數(shù)據(jù),不過(guò)需要注意的是,該方法并不會(huì)影響實(shí)例中off字段的值。

4.3.3 Seek 方法說(shuō)明

func (s *SectionReader) Seek(offset int64, whence int) (int64, error) {
   switch whence {
   default:
      return 0, errWhence
   case SeekStart:
      // s.off = s.base + offset
      offset += s.base
   case SeekCurrent:
      // s.off = s.off + offset
      offset += s.off
   case SeekEnd:
      // s.off = s.limit + offset
      offset += s.limit
   }
   // 檢查
   if offset < s.base {
      return 0, errOffset
   }
   s.off = offset
   return offset - s.base, nil
}

SectionReader也提供了Seek方法,給其提供了隨機(jī)訪問(wèn)和靈活讀取數(shù)據(jù)的能力。舉個(gè)例子,假如已經(jīng)調(diào)用Read方法讀取了一部分?jǐn)?shù)據(jù),但是想要重新讀取該數(shù)據(jù),此時(shí)便可以使Seek方法將off字段設(shè)置回之前的位置,然后再次調(diào)用Read方法進(jìn)行讀取。

五. 使用注意事項(xiàng)

5.1 注意off值在base和limit之間

當(dāng)使用 SectionReader 創(chuàng)建實(shí)例時(shí),確保 off 值在 baselimit 之間是至關(guān)重要的。保證 off 值在 baselimit 之間的好處是確保讀取操作在有效的數(shù)據(jù)范圍內(nèi)進(jìn)行,避免讀取錯(cuò)誤或超出范圍的訪問(wèn)。如果 off 值小于 base 或大于等于 limit,讀取操作可能會(huì)導(dǎo)致錯(cuò)誤或返回 EOF。

一個(gè)良好的實(shí)踐方式是使用 NewSectionReader 函數(shù)來(lái)創(chuàng)建 SectionReader 實(shí)例。NewSectionReader 函數(shù)會(huì)檢查 off 值是否在有效范圍內(nèi),并自動(dòng)調(diào)整 off 值,以確保它在 baselimit 之間。

5.2 及時(shí)關(guān)閉底層數(shù)據(jù)源

當(dāng)使用SectionReader時(shí),如果沒(méi)有及時(shí)關(guān)閉底層數(shù)據(jù)源可能會(huì)導(dǎo)致資源泄露,這些資源在程序執(zhí)行期間將一直保持打開(kāi)狀態(tài),直到程序終止。在處理大量請(qǐng)求或長(zhǎng)時(shí)間運(yùn)行的情況下,可能會(huì)耗盡系統(tǒng)的資源。

下面是一個(gè)示例,展示了沒(méi)有關(guān)閉SectionReader底層數(shù)據(jù)源可能引發(fā)的問(wèn)題:

func main() {
    file, err := os.Open("data.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    section := io.NewSectionReader(file, 10, 20)
    buffer := make([]byte, 10)
    _, err = section.Read(buffer)
    if err != nil {
        log.Fatal(err)
    }
    // 沒(méi)有關(guān)閉底層數(shù)據(jù)源,可能導(dǎo)致資源泄露或其他問(wèn)題
}

在上述示例中,底層數(shù)據(jù)源是一個(gè)文件。在程序結(jié)束時(shí),沒(méi)有顯式調(diào)用file.Close()來(lái)關(guān)閉文件句柄,這將導(dǎo)致文件資源一直保持打開(kāi)狀態(tài),直到程序終止。這可能導(dǎo)致其他進(jìn)程無(wú)法訪問(wèn)該文件或其他與文件相關(guān)的問(wèn)題。

因此,在使用SectionReader時(shí),要注意及時(shí)關(guān)閉底層數(shù)據(jù)源,以確保資源的正確管理和避免潛在的問(wèn)題。

六. 總結(jié)

本文主要對(duì)SectionReader進(jìn)行了介紹。文章首先從一個(gè)基本HTTP文件服務(wù)器的功能實(shí)現(xiàn)出發(fā),解釋了該實(shí)現(xiàn)存在內(nèi)存資源浪費(fèi),并發(fā)性能低等問(wèn)題,從而引出了SectionReader。

接下來(lái)介紹了SectionReader的基本定義,以及其基本使用方法,最后使用SectionReader對(duì)上述HTTP文件服務(wù)器進(jìn)行優(yōu)化。接著還詳細(xì)講述了SectionReader的實(shí)現(xiàn)原理,從而能夠更好得理解和使用SectionReader。

最后,講解了SectionReader的使用注意事項(xiàng),如需要及時(shí)關(guān)閉底層數(shù)據(jù)源等。基于此完成了SectionReader的介紹。

以上就是Golang性能提升利器之SectionReader的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Golang SectionReader的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go并發(fā)編程之死鎖與活鎖的案例分析

    Go并發(fā)編程之死鎖與活鎖的案例分析

    死鎖就是在并發(fā)程序中,兩個(gè)或多個(gè)線程彼此等待對(duì)方完成操作,從而導(dǎo)致它們都被阻塞,并無(wú)限期地等待對(duì)方完成;活鎖就是程序一直在運(yùn)行,但是無(wú)法取得進(jìn)展。本文將從一些案例出發(fā),分析一下它們,希望對(duì)大家有所幫助
    2023-04-04
  • Go疑難雜癥講解之為什么nil不等于nil

    Go疑難雜癥講解之為什么nil不等于nil

    在日常開(kāi)發(fā)中,可能一不小心就會(huì)掉進(jìn)?Go?語(yǔ)言的某些陷阱里,而本文要介紹的?nil?≠?nil?問(wèn)題,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-10-10
  • golang實(shí)現(xiàn)unicode轉(zhuǎn)換為字符串string的方法

    golang實(shí)現(xiàn)unicode轉(zhuǎn)換為字符串string的方法

    這篇文章主要介紹了golang實(shí)現(xiàn)unicode轉(zhuǎn)換為字符串string的方法,實(shí)例分析了Go語(yǔ)言編碼轉(zhuǎn)換的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • golang連接redis庫(kù)及基本操作示例過(guò)程

    golang連接redis庫(kù)及基本操作示例過(guò)程

    這篇文章主要介紹了golang連接redis庫(kù)及基本操作示例過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Golang實(shí)現(xiàn)http文件上傳小功能的案例

    Golang實(shí)現(xiàn)http文件上傳小功能的案例

    這篇文章主要介紹了Golang實(shí)現(xiàn)http文件上傳小功能的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • golang修改結(jié)構(gòu)體中的切片值方法

    golang修改結(jié)構(gòu)體中的切片值方法

    這篇文章主要介紹了golang修改結(jié)構(gòu)體中的切片值方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • golang去除多余的空格與換行符示例代碼

    golang去除多余的空格與換行符示例代碼

    Golang是一種強(qiáng)大的編程語(yǔ)言,提供了豐富的字符串處理功能,這篇文章主要給大家介紹了關(guān)于golang去除多余的空格與換行符的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • Go中sync.Once源碼的深度講解

    Go中sync.Once源碼的深度講解

    sync.Once是Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的一個(gè)同步原語(yǔ),用于確保某個(gè)操作只執(zhí)行一次,本文將從源碼出發(fā)為大家詳細(xì)介紹一下sync.Once的具體使用,x希望對(duì)大家有所幫助
    2025-01-01
  • Go語(yǔ)言程序查看和診斷工具詳解

    Go語(yǔ)言程序查看和診斷工具詳解

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言程序查看和診斷工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • go值賦值和引用賦值的使用

    go值賦值和引用賦值的使用

    本文將介紹Go語(yǔ)言中的值賦值和引用賦值,并比較它們之間的差異,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-10-10

最新評(píng)論