一文詳解Go語言io包中的discard類型
1. 引言
io.discard
是Go語言標(biāo)準(zhǔn)庫提供一個(gè)結(jié)構(gòu)體類型,其在丟棄不需要的數(shù)據(jù)場景下非常好用。
本文我們將從io.discard
類型的基本定義出發(fā),講述其基本使用和實(shí)現(xiàn)原理,接著簡單描述 io.discard
的使用場景,基于此完成對 io.discard
類型的介紹。
2. 介紹
2.1 基本定義
io.discard
是 Go語言提供的一個(gè)Writer
,這個(gè)Writer
比較特殊,其不會(huì)做任何事情。它會(huì)將寫入的數(shù)據(jù)立即丟棄,不會(huì)做任何處理。其定義如下:
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
結(jié)構(gòu)體類型沒有定義任何字段,同時(shí)還提供了Write
,ReadFrom
和WriteString
方法,Write
方法和WriteString
方法分別接收字節(jié)切片和字符串,然后返回寫入的字節(jié)數(shù)。
同時(shí)還實(shí)現(xiàn)了io.ReaderFrom
接口,這個(gè)是為了在使用 io.Copy
函數(shù)時(shí),將數(shù)據(jù)從源復(fù)制到io.discard
時(shí),避免不必要的操作。
從上面discard
的定義可以看起來,其不是一個(gè)公開類型的結(jié)構(gòu)體類型,所以我們并不能創(chuàng)建結(jié)構(gòu)體實(shí)例。事實(shí)上Go語言提供了一個(gè)io.discard
實(shí)例的預(yù)定義常量,我們直接使用,無需自己創(chuàng)建實(shí)例,定義如下:
var Discard Writer = discard{}
2.2 使用說明
下面通過一個(gè)丟棄網(wǎng)絡(luò)連接中不再需要的數(shù)據(jù)的例子,來展示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("連接錯(cuò)誤:", err) return } defer conn.Close() bytesToDiscard := int64(1024) // 要丟棄的字節(jié)數(shù) err = discardData(conn, bytesToDiscard) if err != nil { fmt.Println("丟棄數(shù)據(jù)錯(cuò)誤:", err) return } fmt.Println("數(shù)據(jù)已成功丟棄。") }
在上面示例中,我們建立了網(wǎng)絡(luò)連接,然后連接中的前1024個(gè)字節(jié)的數(shù)據(jù)是不需要的。這個(gè)時(shí)候,我們通過io.CopyN
函數(shù)將數(shù)據(jù)從conn
拷貝到io.Discard
當(dāng)中,基于io.Discard
丟棄數(shù)據(jù)的特性,成功將連接的前1024個(gè)字節(jié)丟棄掉,而不需要自定義緩沖區(qū)之類的操作,簡單高效。
3. 實(shí)現(xiàn)原理
io.Discard
的目的是在某些場景下提供一個(gè)滿足io.Writer
接口的實(shí)例,但用戶對于數(shù)據(jù)的寫入操作并不關(guān)心。它可以被用作一個(gè)黑洞般的寫入目標(biāo),默默地丟棄所有寫入它的數(shù)據(jù)。所以io.discard
的實(shí)現(xiàn)也相對比較簡單,不對輸入的數(shù)據(jù)進(jìn)行任何處理即可,下面我們來看具體的實(shí)現(xiàn)。
首先是io.discard
結(jié)構(gòu)體的定義,沒有定義任何字段,因?yàn)楸緛硪膊恍枰獔?zhí)行任何寫入操作:
type discard struct{}
而對于Write
和 WriteString
方法,其直接返回了傳入?yún)?shù)的長度,往該Writer
寫入的數(shù)據(jù)不會(huì)被寫入到其他地方,而是被直接丟棄:
func (discard) Write(p []byte) (int, error) { return len(p), nil } func (discard) WriteString(s string) (int, error) { return len(s), nil }
同時(shí)discard
也實(shí)現(xiàn)了io.ReaderFrom
接口,實(shí)現(xiàn)了ReadFrom
方法,實(shí)現(xiàn)也是非常簡單,從blackHolePool
緩沖池中獲取字節(jié)切片,然后不斷讀取數(shù)據(jù),讀取完成之后,再將字節(jié)切片重新放入緩沖池當(dāng)中:
// 存在一個(gè)字節(jié)切片緩沖池 var blackHolePool = sync.Pool{ New: func() any { b := make([]byte, 8192) return &b }, } func (discard) ReadFrom(r Reader) (n int64, err error) { // 從緩沖池中取出一個(gè) 字節(jié)切片 bufp := blackHolePool.Get().(*[]byte) readSize := 0 for { // 不斷讀取數(shù)據(jù),bufp 只是作為一個(gè)讀取數(shù)據(jù)的中介,讀取到的數(shù)據(jù)并無意義 readSize, err = r.Read(*bufp) n += int64(readSize) if err != nil { // 將字節(jié)切片 重新放入到 blackHolePool 當(dāng)中 blackHolePool.Put(bufp) if err == EOF { return n, nil } return } } }
在io.Copy
函數(shù)中,將調(diào)用discard
中的ReadFrom
方法,能夠?qū)?code>Writer中的所有數(shù)據(jù)讀取完,然后丟棄掉。
4. 使用場景
io.Discard
給我們提供了一個(gè)io.Writer
接口的實(shí)例,同時(shí)其又不會(huì)真實(shí)得寫入數(shù)據(jù),這個(gè)在某些場景下非常有用。
有時(shí)候,我們可能需要一個(gè)實(shí)現(xiàn)io.Writer
接口的實(shí)例,但是我們并不關(guān)心數(shù)據(jù)寫入Writer
的結(jié)果,也不關(guān)心數(shù)據(jù)是否寫到了哪個(gè)地方,此時(shí)io.Discard
就給我們提供了一個(gè)方便的解決方案。同時(shí)io.Discard
可以作為一個(gè)黑洞寫入目標(biāo),能夠?qū)?shù)據(jù)默默丟棄掉,不會(huì)進(jìn)行實(shí)際的處理和存儲(chǔ)。
所以如果我們想要丟棄某些數(shù)據(jù),亦或者是需要一個(gè)io.Writer
接口的實(shí)例,但是對于寫入結(jié)果不需要關(guān)注時(shí),此時(shí)使用io.Discard
是非常合適的。
5. 總結(jié)
io.discard
函數(shù)是Go語言標(biāo)準(zhǔn)庫中一個(gè)實(shí)現(xiàn)了Writer
接口的結(jié)構(gòu)體類型,能夠悄無聲息得實(shí)現(xiàn)數(shù)據(jù)的丟棄。 我們先從io.discard
類型的基本定義出發(fā),之后通過一個(gè)簡單的示例,展示如何使用io.discard
類型實(shí)現(xiàn)對不需要數(shù)據(jù)的丟棄。
接著我們講述了io.discard
類型的實(shí)現(xiàn)原理,其實(shí)就是不對寫入的數(shù)據(jù)執(zhí)行任何操作。在使用場景下,我們想要丟棄某些數(shù)據(jù),亦或者是需要一個(gè)io.Writer
接口的實(shí)例,但是對于寫入結(jié)果不需要關(guān)注時(shí),此時(shí)使用io.Discard
是非常合適的。
基于此,便完成了對io.discard
類型的介紹,希望對你有所幫助。
以上就是一文詳解Go語言io包中的discard類型的詳細(xì)內(nèi)容,更多關(guān)于Go語言io包discard類型的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Go語言解析動(dòng)態(tài)JSON格式的方法
本篇文章主要介紹了使用Go語言解析動(dòng)態(tài)JSON格式的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12在Go中實(shí)現(xiàn)高效可靠的鏈路追蹤系統(tǒng)
在當(dāng)今互聯(lián)網(wǎng)應(yīng)用的架構(gòu)中,分布式系統(tǒng)已經(jīng)成為主流,分布式系統(tǒng)的優(yōu)勢在于能夠提供高可用性、高并發(fā)性和可擴(kuò)展性,本文將介紹鏈路追蹤的概念和原理,并重點(diǎn)介紹如何在Golang中實(shí)現(xiàn)高效可靠的鏈路追蹤系統(tǒng),需要的朋友可以參考下2023-10-10Go實(shí)現(xiàn)List、Set、Stack、Deque等數(shù)據(jù)結(jié)構(gòu)的操作方法
Go語言團(tuán)隊(duì)的一個(gè)核心目標(biāo)是保持語言的簡單性,他們認(rèn)為,如果一個(gè)功能可以用簡單的組合來實(shí)現(xiàn),那就沒有必要把它放進(jìn)標(biāo)準(zhǔn)庫里,本文給大家介紹Go實(shí)現(xiàn)List、Set、Stack、Deque等數(shù)據(jù)結(jié)構(gòu)的操作方法,感興趣的朋友跟隨小編一起看看吧2024-12-12Golang 獲取系統(tǒng)信息的實(shí)現(xiàn)
本文主要介紹了Golang 獲取系統(tǒng)信息的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06提升Golang應(yīng)用性能:深入理解Context的應(yīng)用
本文將深入探討如何通過深入理解和正確應(yīng)用Go語言中的Context來提升應(yīng)用性能。需要的朋友可以參考下2023-09-09