一文瞭解io包中的discard類型

来源:https://www.cnblogs.com/chenjiazhan/archive/2023/07/13/17549324.html
-Advertisement-
Play Games

相信熟悉 Golang 的小伙伴不少都知道 `條件編譯` 這個事,最近項目中也可能會用到這個東西。所以特意重新學習下,記錄下學習的過程。這樣用的時候記不住了,還可以直接過來看自己的筆記。 > 文章很多內容來源於參考資料,感謝。 ### 1、條件編譯簡介 #### 1.1、為什麼需要條件編譯 在實際的 ...


1. 引言

io.discard是Go語言標準庫提供一個結構體類型,其在丟棄不需要的數據場景下非常好用。本文我們將從io.discard 類型的基本定義出發,講述其基本使用和實現原理,接著簡單描述 io.discard 的使用場景,基於此完成對 io.discard 類型的介紹。

2. 介紹

2.1 基本定義

io.discard 是 Go語言提供的一個Writer,這個Writer 比較特殊,其不會做任何事情。它會將寫入的數據立即丟棄,不會做任何處理。其定義如下:

type discard struct{}
func (discard) Write(p []byte) (int, error) {}
func (discard) WriteString(s string) (int, error) {}
func (discard) ReadFrom(r Reader) (n int64, err error) {}

discard 結構體類型沒有定義任何欄位,同時還提供了Write ,ReadFromWriteString 方法,Write 方法和WriteString 方法分別接收位元組切片和字元串,然後返回寫入的位元組數。

同時還實現了io.ReaderFrom 介面,這個是為了在使用 io.Copy 函數時,將數據從源複製到io.discard 時,避免不必要的操作。

從上面discard 的定義可以看起來,其不是一個公開類型的結構體類型,所以我們並不能創建結構體實例。事實上Go語言提供了一個io.discard 實例的預定義常量,我們直接使用,無需自己創建實例,定義如下:

var Discard Writer = discard{}

2.2 使用說明

下麵通過一個丟棄網路連接中不再需要的數據的例子,來展示io.Discard 的使用,代碼示例如下:

package main

import (
        "fmt"
        "io"
        "net"
        "os"
)

func discardData(conn net.Conn, bytesToDiscard int64) error {
        _, err := io.CopyN(io.Discard, conn, bytesToDiscard)
        return err
}

func main() {
        conn, err := net.Dial("tcp", "example.com:80")
        if err != nil {
                fmt.Println("連接錯誤:", err)
                return
        }
        defer conn.Close()

        bytesToDiscard := int64(1024) // 要丟棄的位元組數

        err = discardData(conn, bytesToDiscard)
        if err != nil {
                fmt.Println("丟棄數據錯誤:", err)
                return
        }

        fmt.Println("數據已成功丟棄。")
}

在上面示例中,我們建立了網路連接,然後連接中的前1024個位元組的數據是不需要的。這個時候,我們通過io.CopyN 函數將數據從conn 拷貝到io.Discard 當中,基於io.Discard 丟棄數據的特性,成功將連接的前1024個位元組丟棄掉,而不需要自定義緩衝區之類的操作,簡單高效。

3. 實現原理

io.Discard的目的是在某些場景下提供一個滿足io.Writer介面的實例,但用戶對於數據的寫入操作並不關心。它可以被用作一個黑洞般的寫入目標,默默地丟棄所有寫入它的數據。所以io.discard 的實現也相對比較簡單,不對輸入的數據進行任何處理即可,下麵我們來看具體的實現。

首先是io.discard 結構體的定義,沒有定義任何欄位,因為本來也不需要執行任何寫入操作:

type discard struct{}

而對於WriteWriteString 方法,其直接返回了傳入參數的長度,往該Writer 寫入的數據不會被寫入到其他地方,而是被直接丟棄:

func (discard) Write(p []byte) (int, error) {
   return len(p), nil
}

func (discard) WriteString(s string) (int, error) {
   return len(s), nil
}

同時discard 也實現了io.ReaderFrom 介面,實現了ReadFrom 方法,實現也是非常簡單,從blackHolePool 緩衝池中獲取位元組切片,然後不斷讀取數據,讀取完成之後,再將位元組切片重新放入緩衝池當中:

// 存在一個位元組切片緩衝池
var blackHolePool = sync.Pool{
   New: func() any {
      b := make([]byte, 8192)
      return &b
   },
}

func (discard) ReadFrom(r Reader) (n int64, err error) {
   // 從緩衝池中取出一個 位元組切片
   bufp := blackHolePool.Get().(*[]byte)
   readSize := 0
   for {
      // 不斷讀取數據,bufp 只是作為一個讀取數據的中介,讀取到的數據並無意義
      readSize, err = r.Read(*bufp)
      n += int64(readSize)
      if err != nil {
         // 將位元組切片 重新放入到 blackHolePool 當中
         blackHolePool.Put(bufp)
         if err == EOF {
            return n, nil
         }
         return
      }
   }
}

io.Copy 函數中,將調用discard 中的ReadFrom 方法,能夠將Writer中的所有數據讀取完,然後丟棄掉。

4. 使用場景

io.Discard 給我們提供了一個io.Writer 介面的實例,同時其又不會真實得寫入數據,這個在某些場景下非常有用。

有時候,我們可能需要一個實現io.Writer 介面的實例,但是我們並不關心數據寫入Writer 的結果,也不關心數據是否寫到了哪個地方,此時io.Discard 就給我們提供了一個方便的解決方案。同時io.Discard 可以作為一個黑洞寫入目標,能夠將數據默默丟棄掉,不會進行實際的處理和存儲。

所以如果我們想要丟棄某些數據,亦或者是需要一個io.Writer介面的實例,但是對於寫入結果不需要關註時,此時使用io.Discard 是非常合適的。

5. 總結

io.discard 函數是Go語言標準庫中一個實現了Writer介面的結構體類型,能夠悄無聲息得實現數據的丟棄。 我們先從io.discard 類型的基本定義出發,之後通過一個簡單的示例,展示如何使用io.discard 類型實現對不需要數據的丟棄。

接著我們講述了io.discard 類型的實現原理,其實就是不對寫入的數據執行任何操作。在使用場景下,我們想要丟棄某些數據,亦或者是需要一個io.Writer介面的實例,但是對於寫入結果不需要關註時,此時使用io.Discard 是非常合適的。

基於此,便完成了對io.discard 類型的介紹,希望對你有所幫助。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 追憶Scoped 偶然想起了一次面試,二面整體都聊完了,該做的演算法題都做出來了,該背的八股文也背的差不多了,面試官頻頻點頭,似乎對我的基礎和項目經驗都很是滿意。嗯,我內心os本次面試應該十拿九穩了。 突然,面試官說:「我的主技術棧是Rea ...
  • 雖然第三方表格插件多不勝數,但是很多場景還是需要用到原生<table>,掌握html原生table的實現方法,是前端開發的必備技能。例如:print-js列印、html2canvas生成圖片等,用原生table可以規避很多問題。 首先,在寫原生<table>之前,我們先認識一下 border-col ...
  • 1.頁面結構 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> </body> </html> 編碼:charset=“gbk” ;gbk2312,utf-8 2.常見標簽 2.1 ...
  • ## 引言 軟體開發過程中,我們經常會遇到各種設計問題,例如如何管理對象之間的關係、如何優化代碼的可復用性和可維護性等等。為瞭解決這些問題,我們可以使用設計模式。 設計模式是一種被廣泛接受的軟體設計思想,它提供了一套通用的解決方案,可以幫助我們更好地解決常見的軟體設計問題。設計模式是從實踐中總結出來 ...
  • 本文詳細介紹了搭建系統工程架構時需要關註的幾個重要方面。基於產品的價值,做出決策。並從系統工程架構的演進、技術方案的選型、系統規範共識的達成等方面入手,對實施過程中的常見問題給出瞭解決思路。 ...
  • 清晰架構是將領域驅動、整潔架構等架構的部分優勢整合之後產生的另一種架構,因其2017年已經出現,已經不算是一種新的架構,實際應用的項目尚且較少。以下主要介紹架構的形成及各步驟的意義 ...
  • ## 引言 **責任鏈模式**是一種行為型設計模式,它通過一條由多個處理器組成的鏈來處理請求,每個處理器都有機會處理請求,如果一個處理器不能處理該請求,它會將請求傳遞給下一個處理器,直到請求被處理為止。 在實際應用中,責任鏈模式常用於處理請求的分發、事件處理等場景,它的優點在於可以動態地添加、刪除處 ...
  • 一、表結構設計 二、實現思路 1.系統啟動時將字典數據載入到redis作為可選常量池,以及mapper.xml、dao、數據規則信息載入到redis 2.用訪問時通過springmvc攔截器對用戶進行攔截獲取token然後通過RSA解密獲取用戶信息,將用戶信息,以及請求參數加入本地線程 3.myba ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...