一文了解io包中的discard类型

这篇具有很好参考价值的文章主要介绍了一文了解io包中的discard类型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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 类型的介绍,希望对你有所帮助。文章来源地址https://www.toymoban.com/news/detail-552996.html

到了这里,关于一文了解io包中的discard类型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【⑬MySQL】· 一文了解数据类型(一)

    ✨欢迎来到小K的MySQL专栏,本节将为大家带来MySQL数据类型简介 | 整数 | 浮点 | 定点 | 时间/日期类型的分享 ✨ 0.数据类型简介 数据类型(data_type)是指系统中所允许的数据的类型。MySQL 数据类型定义了列中可以存储什么数据以及该数据怎样存储的规则。 数据库中的每个列都

    2024年02月11日
    浏览(28)
  • 一文了解 | 系统测试与集成测试有哪些类型和优势?

    作者的话 在软件开发生命周期(SDLC)中,每个软件都要经历多次质量检查,从而确保产品质量。但说起来容易做起来难。虽然敏捷框架改善了测试过程中的沟通和协作,但许多有经验的测试人员在测试过程中仍然会遇到不确定性。 他们知道集成测试在系统测试之前,但发现

    2024年02月13日
    浏览(29)
  • 【JAVA】一文带你了解java的数据类型与变量

    作者主页:paper jie的博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将javaSE基础知识一网打尽,希望可以帮到读者们哦。 其他专栏

    2024年02月14日
    浏览(30)
  • 一文了解SpringBoot中的Aop

    目录 1.什么是Aop 2.相关概念 3.相关注解 4.为什么要用Aop 5.Aop使用案例 1.什么是Aop AOP :Aspect Oriented Programming, 面向切面 ,是Spring三大思想之一,另外两个是 IOC-控制反转 DI-依赖注入 ( @Autowired、@Qualifier、@Resource ) 2.相关概念 切面(aspect): 横切面对象,一般为一个具体类对象(可

    2024年02月11日
    浏览(31)
  • 一文带你了解:Linux 文件系统+文件系统相关 Shell 命令+文件系统类型

    本篇文章是记录我在学习Linux时,有关Linux 文件系统的学习。 操作系统的基本功能之一就是文件管理,而文件的管理是由文件系统来完成的。 Linux 支持多种文件系统,接下来我们就来一起了解 Linux 下的 文件系统、文件系统类型、文件系统结构和文件系统相关 Shell 命令。 有

    2024年02月22日
    浏览(35)
  • 【MySQL】数据库中这么多数据类型你真的了解吗?一文看懂不同数据类型有何区别

    创建表t1,将name列数据类型设置为要tinyint 插入属性值:由于这里是tinyint类型,取值范围是【-128–127】,当插入这个范围内的数据显示成功,范围之外失败 使用tinyint unsigned类型创建表t2 无符号类型取值范围【0,255】,这点与C/C++一样 2.1.1 小结 MySQL对于数据类型不合法行为采

    2024年02月13日
    浏览(29)
  • 一文了解Python中的注释及变量

    目录 🥩1.注释 🍕1.1.注释 🍕1.2.注释分类 🥩2.变量 🌮2.1.变量的定义 🌮2.2.变量的类型 🌮2.3.查看数据类型 🌮2.4.命名规范 🌮2.5.类型转换 🍣2.5.1.转换为整数 🍣2.5.2.转换为浮点数 🍣2.5.3.转换为字符串 🍣2.5.4.转换为布尔类型      🦐博客主页:大虾好吃吗的博客    

    2024年02月12日
    浏览(32)
  • 【云原生】· 一文了解docker中的网络

    目录 🍒查看docker网络 🍒bridge网络 🍒none网络 🍒host网络 🍒自定义容器网络     🦐博客主页:大虾好吃吗的博客     🦐专栏地址:云原生专栏         根据前面的学习,已经对docker有了一些简单的概念。这里在啰嗦一句, 容器是一个独立的环境 ,可以理解为一个小

    2024年02月09日
    浏览(33)
  • 【云原生】 一文了解docker中的网络

    例如:bridge(桥接)、host(主机)、overlay(覆盖)和macvlan(MACVLAN)等。这意味着可以根据具体的场景和需求来选择使用哪一种网络驱动程序。 在该模式下,容器将配置为使用Docker守护进程上的bridge网络。这使得所有同一网络的容器都能够相互通信,并且可以使用连接到宿

    2024年02月14日
    浏览(27)
  • 一文了解Python中的while循环语句

    目录 🥩循环语句是什么 🥩while循环 🥩遍历猜数字 🥩while循环嵌套 🥩while循环嵌套案例      🦐博客主页:大虾好吃吗的博客      🦐专栏地址:Python从入门到精通专栏         循环语句在编程中非常有用,可以帮助我们重复执行特定的代码块,从而实现一些重复性

    2024年02月15日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包