GO语言核心30讲 实战与应用 (io包,bufio包,os包,网络服务,http,性能分析)

 原站地址:Go语言核心36讲_Golang_Go语言-极客时间

一、io包中的接口和工具

1. strings.Builder、strings.Reader 和 bytes.Buffer 这些类型实现了 io 包的很多接口,目的是什么?

    是为了提高不同程序实体之间的互操作性。 程序实体是指比如网络和文件。

    比如 io.Copy:  func Copy(dst Writer, src Reader) (written int64, err error)

    里面的 Writer 和 Reader 可以是网络,也可以是文件,只要实现了io.Reader接口和io.Writer接口就都可以了。可以把不同的实体抽象成一个统一的实体。

2. 扩展接口和实现类型的区别是什么?

   实现类型是一个结构体; 扩展接口只是通过结构体的方式,嵌入了其他数据类型,达到扩展原有数据类型功能的目的,

   扩展接口是多个接口的集合。要实现扩展接口,需要实现多个接口。

   实现类型是把接口实现了,而扩展接口并没有把接口实现,它只是多个接口的集合。

3. 在io包中,io.Reader的扩展接口和实现类型都有哪些? (提升对io包的了解程度)

    io.Reader的扩展接口有下面几种:

(1) io.ReadWriter:包含字节序列读取方法Read,和写入方法Write。

(2) io.ReadCloser:包含字节序列读取方法Read,和关闭方法Close。Close用于关闭数据读写的通路。这个接口是io.Reader和io.Closer的组合。

(3) io.ReadWriteCloser:io.Reader、io.Write 和io.Closer的组合。

(4) io.ReadSeeker:可以根据给定的偏移量去寻找新的位置,作为下一次读的起始索引。包含了寻找读写位置的基本方法Seek。io.Reader 和io.Seeker的组合。

(5) io.ReadWriteSeeker:io.Reader、io.Writer和io.Seeker的组合。

   io.Reader接口的实现类型有下面几种:

(1) *io.LimitedReader:方法Read返回的总数据量会受到限制,无论被调用多少次。

(2) *io.SectionReader:Read方法只能够读取原始数据中的某一个部分。与切片类似,只暴露在窗口之中的数据。

(3) *io.teeReader:接受io.Reader和io.Writer两个类型的参数,把Reader读到的数据,通过字节切片中转的方式,写入io.Writer处。通常使用在数据流的处理中,比如计算下载速度。

(4) *io.multiReader:接受多个io.Reader类型的参数,并从中顺序地读取数据。

(5) *io.pipe:同步内存管道的核心实现

(6) * io.PipeReader:同步内存管道的读取端

4. io包中的接口都有哪些?

(1) 核心接口:io.Reader、io.Writer和io.Closer

(2) io.ByteReader:读取一个单一的字节。 strings.Reader和bytes.Buffer 是它的实现类型。

     io.RuneReader:读取一个单一的Unicode 字符。strings.Reader和bytes.Buffer 是其实现类型

     io.ByteScanner:读取和读回退单个字节

     io.RuneScanner:读取和读回退单个Unicode 字符

     io.ReaderAt:只读取数据,不修改已读计数的值。

     io.ReaderFrom:从一个 Reader 中读取数据

     io.WriteTo:将数据写入到一个 Writer 中

     io.ReadWriter:读和写, *io.pipe 是其实现类型。

     io.ReadWriteCloser:读写和关闭管道,net包有它的实现类型。

     io.ByteWriter和io.WriterAt:功能和上面对应。实现类型是 *os.File

     io.Seeker:寻找并设定下一次读取或写入时的起始索引位置。strings.Reader和io.SectionReader都是其实现类型。

    io.Closer:关闭管道。io.PipeReader和io.PipeWriter 是其实现类型。

(3) io包中的简单接口共有 11 个。读取操作相关的5 个,写入操作相关的 4 个,关闭操作有关的1 个,读写位置设定相关的一个。此外,还包含了 9 个基于这些简单接口的扩展接口。

二、bufio包中的数据类型

1. bufio 包的程序实体,是在包装简单 I/O 接口类型值的基础上,添加了缓冲区。

2. bufio包中的数据类型主要有:(1) Reader (2) Scanner (3) Writer 和 ReadWriter。

3. bufio.Reader类型值中的缓冲区起着怎样的作用?

        Reader值会预先从底层读取器里读出一部分数据,暂存于缓冲区之中。当Reader值下次读取数据时,先从缓冲区中读取。 减少了底层读取器的使用次数,降低读取的执行时间。 

        虽然,读取时会增加填充缓冲区的操作,但从总体上看,平均执行时间会有大幅度的缩短。

4. bufio.Reader类型通过私有的 fill方法 来整理缓冲区,把已读的空间腾出来,提供给底层读取器存放数据。

    整理方法就是把 [已读计数, 已写计数) 范围内的数据往最前面搬运,如下图所示:

5. bufio.Reader类型读取方法分别有哪些?

(1) Peek方法:读取缓冲区中的n个未读字节,n大于缓冲区长度的话,转而直接从底层读取器中读出数据。

      会从已读计数代表的索引位置开始读,读完不更改已读计数。 

(2) Read方法:其他和Peek方法一样,但会更改已读计数。 

(3) ReadSlice方法:持续地读取数据,直至遇到调用方给定的分隔符为止。

     如果缓冲区满了仍然找不到分隔符,会把整个缓冲区作为第一个结果值,缓冲区已满错误作为第二个结果值 返回。

(4) ReadBytes方法: 其他和ReadSlice方法一样,但缓冲区满了仍然找不到分隔符的话,会再次调用ReadSlice方法,整理缓冲区之后继续从底层读取器中读出数据,直至少找到分隔符或者读完全部数据。

6. 内容泄露:Peek方法、ReadSlice方法和ReadLine方法都有可能会造成内容泄露,因为他们都是返回直接基于缓冲区的字节切片。 只有Read方法不会内容泄露。

三、使用os包中的API

1. os代码包中的 API,是对操作系统的某方面功能的高层次抽象,使我们可以用统一的方式,操纵不同的操作系统。

    最有代表性的就是数据类型 os.File,它实现了io包3 个核心接口io.Reader、io.Writer和io.Closer,3 个简单接口,io.ReaderAt、io.Seeker和io.WriterAt,以及9 个扩展接口中的 7 个。

    所以除 文本文件、二进制文件、压缩文件、目录这些常见的形式之外,还有符号链接、各种物理设备、命名管道,以及套接字(socket)都可以被视为文件。

2. 怎样才能获得一个os.File类型的指针值(File值)? 

(1) os.Create函数:根据给定的路径创建一个新的文件。 

      会返回一个File值和一个错误值。可以通过File值进行读写,路径不存在的话会返回错误。

(2) os.Open函数:打开一个文件并返回包装了该文件的File值。

      只能从该File值中读取内容,而不能写入内容。

(3) os.NewFile函数:依据已经存在的文件描述符,新建包装了该文件的File值。

(4) os.OpenFile函数:新建或打开文件。

     可读可写。函数有 3 个参数,为name(文件路径)、flag(操作模式)和perm(权限模式)。

     可以视为这是基础函数,上面3个函数只是这个基础函数的参数组合。

3. 文件描述符,作为某个文件的一个标识存在。由 I/O 相关的系统调用返回,是很小的非负整数。

    任何文件的I/O 操作都需要这个文件描述符,它被存储在File值中。

4. File值的操作模式都有哪些?

    os.O_APPEND:追加模式写入内容。

    os.O_CREATE:路径不存在时创建文件。

    os.O_SYNC:在打开的文件上实施同步 I/O,保证读写的内容总会与硬盘上的数据同步。

    os.O_TRUNC:文件已存在时清空文件内容。

    多个操作模式可以通过按位或操作符 " | " 组合起来的。

5. File值的权限模式都有哪些?

    权限模式参数 是uint32类型的再定义类型,包含了 32 个比特位,每个比特位都有特定含义:

(1) 最高比特位,1 代表 目录。

(2) 第 26 个比特位,1代表 命名管道

(3) 最低的 9 个比特位才用于文件的权限,分别是 文件所有者、用户组、其他用户 对该文件的访问权限(读、写和执行)。

四、访问网络服务

1. 进程间通信,称为 IPC。主要方法包括:系统信号(signal)、管道(pipe)、套接字(socket)、文件锁、消息队列、信号量(semaphore)等。 socket 是最为通用和灵活的一种。

2. socket实例相关的API,是由一个名为 socket系统调用 代表的,它是连接应用程序和操作系统内核的桥梁。

    syscall代码包中,有一个与这个 socket系统调用 相对应的函数。函数本身是平台不相关的。在其底层,Go 为每个操作系统都做了适配,所以无论在哪个平台上总是有效的。

    net代码包中的很多程序实体,都会直接或间接地使用到syscall.Socket函数,比如net.Dial函数

3. net.Dial函数的第一个参数network有哪些可选值?

(1) TCP、TCP4、TCP6:代表 TCP 协议,自适应、第四版、第六版

(2) UDP、UDP4、UDP6:代表 UDP 协议,自适应、第四版、第六版

(3) unix、unixgram、unixpacket:代表 Unix 通信域下的内部 socket 协议,socket 类型分别为SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET。

4. 有消息边界,是指内核程序在发送或接收数据时,是以消息为单位的。

    有逻辑连接,是指通信双方在收发数据之前必须先建立网络连接。

5. TCP 没有消息边界,有逻辑连接。 好处:保证可靠性,有序,双向传输。坏处:速度慢。

    UDP 有消息边界,没有逻辑连接。好处:速度快。坏处:不保证可靠,无需,只能单向传输。

6. net.DialTimeout函数 调用时给定的超时时间意味着什么?

   给定的超时时间,意味着函数为网络建立连接,可以等待的最长时间。

   调用net.DialTimeout函数之后,时间主要花费在 “解析参数network和address的值”,以及“创建 socket 实例并建立网络连接”这两件事情上。

五、基于HTTP协议的网络服务

1. net/http代码包 可以使用 基于http协议的网络服务。比如 http.Get函数。

    实例:  resp, err := http.Get(url)    返回两个值:resp 和 err

    resp:数据类型是*http.Response,响应内容的结构体。

    err:数据类型是error,创建、发送请求、接收和解析、响应 全过程中,可能发生的错误。

2. http.Get函数

    http.Get函数会在内部使用 缺省HTTP客户端,它是 net/http包中的公开变量DefaultClient代表的,其类型是 *http.Client, 它是开箱即用的。

3. http.Client类型中的 Transport字段 代表着什么?

(1) Transport字段 的数据类型是 *http.Transport,会在内部使用net.Dialer类型值,实现 连接 和 超时 的功能。

(2) http.Transport类型的值(以下简称Transport值)会对每一个网络服务的空闲连接的总数做出限定。 一个网络服务由网络地址、网络协议、代理 三方面来鉴定。

     在默认情况下,空闲连接总数最大为100,而每个网络服务的最大空闲连接数为2。

(3) *http.Transport 是 http.RoundTripper接口 的实现类型。RoundTripper 内部有一个DefaultTransport的缺省值。 前面提到的 缺省HTTP客户端 DefaultClient ,其实也就是使用这个DefaultTransport。

(4) 总的来说 Transport字段代表着:向网络服务发送 HTTP 请求,并从网络服务接收 HTTP 响应的整个操作过程。

4. http.Server类型的ListenAndServe方法都做了哪些事情?

(1) 对一个基于 TCP 协议的网络地址进行监听(net.Listen),并对接收到的 HTTP 请求进行处理。

(2) 默认开启针对网络连接的存活探测机制,以保证连接是持久的。

(3) 该方法会一直执行,直到有严重的错误发生或者被外界关掉。

5. net.Listen函数都做了哪些事情?

(1) 解析参数值中网络地址包含的 IP 地址和端口号;

(2) 根据给定的网络协议,确定监听的方法,并开始进行监听。

6. http.Server类型的Serve方法是怎样接受和处理 HTTP 请求的?

(1) listen之后,进入一个for循环。

(2) for循环中,Accept方法会被不断地调用,该方法返回两个值:

     net.Conn类型:代表包含了新到来的 HTTP 请求的网络连接

     error类型:代表是否发生了错误。暂时性的错误的话for会继续执行,否则会for循环都会被终止

(3) 把 net.Conn类型的结果值包装成一个*http.conn类型,并启用新的 goroutine ,去调用这个conn值的serve方法,来对当前的 HTTP 请求进行处理。

六、程序性能分析基础

1. 性能分析 API 在这三个代码包中:

(1) runtime/pprof

(2) net/http/pprof

(3) runtime/trace

2. 概要文件(Profile)

   runtime 代码包中包含更底层的 API,用来收集程序运行过程中的一些关键指标,并生成概要文件,提供分析使用。

    go test 命令也可以在测试完成后生成 概要文件(Profile)。

3. 概要文件采样时刻的内容

      分析程序性能的概要文件有CPU、内存、阻塞三种概要文件。文件里每段概要信息都记录着,某个采样时刻的内容分别是:

(1) CPU 概要文件:CPU 上正在执行的 Go 代码。

(2) 内存概要文件:内存的使用情况,已分配和已释放的字节数量和对象数量。

(3) 阻塞概要文件:goroutine 阻塞事件

4. 概要文件内容格式

    这些概要文件是以二进制存储的,是通过 protocol buffers 生成的二进制字节流。

    可以使用 go tool pprof 工具查看。

5. 怎样让程序对 CPU 概要信息进行采样?

(1) 进行采样调用StartCPUProfile函数;停止采样调用StopCPUProfile函数。

(2) StartCPUProfile函数,会设定 CPU 概要信息的采样频率,并在单独的 goroutine 中进行收集和输出。 CPU采样频率总是固定100赫兹的,经过大量实验证明最优。

(3) StopCPUProfile函数,会采样频率设为0,采样工作停止。

6. 怎样设定内存概要信息的采样频率?

(1) 为 runtime.MemProfileRate变量赋值即可。 含义是,每分配多少个字节,就对堆内存的使用情况进行一次采样。缺省值是512 KB。

(2) 越早设定越好,避免运行时造成不良影响。最好只在main函数的开始处设定一次。

(3) 想获取内存概要信息的时候, 调用WriteHeapProfile函数。但它并非实时数据,是在最近一次的内存垃圾收集工作完成时产生的。

(4) 可以调用runtime.ReadMemStats函数,获得实时数据。不过该函数会引起 Go 语言调度器的短暂停顿。

7. 怎样获取到阻塞概要信息?

(1) 调用runtime包中的SetBlockProfileRate函数,可对阻塞概要信息的采样频率进行设定。

(2) 函数有一个名叫rate的参数,int类型。含义是,只要发现一个阻塞事件的持续时间达到了多少纳秒,就对其进行采样。

(3) 在runtime包中,有一个名叫blockprofilerate的私有变量,uint64类型。含义是,只要发现一个阻塞事件的持续时间跨越了多少个 CPU 时钟周期,就对其进行采样。和(2)的区别仅仅在于单位不同。 

(4) 缺省值是0,所以默认情况下并不会记录任何阻塞事件。

(5) 需要获取阻塞概要信息的时候,做两步操作:

    调用runtime/pprof包中的 Lookup函数 并传入参数值"block",得到*runtime/pprof.Profile类型的值     

    调用Profile值的 WriteTo方法,把概要信息写进指定的写入器中。

8. runtime/pprof.Lookup函数的正确调用方式是什么?

(1) Lookup函数的功能是,提供 给定的名称 相对应的概要信息。

(2) 给定的名称 包括:

goroutine:收集当前正在使用的所有 goroutine 堆栈跟踪信息。会引起 Go 调度器的短暂停顿。

heap:收集与堆内存的分配和释放有关的采样信息。也就是前面的内存概要信息。

allocs:与heap大致一样,但 allocs 收集到的是已分配空间(已分配不管有否释放),heap是在用空间(已分配未释放)。

threadcreate:收集堆栈跟踪信息,描绘出代码调用链。

block:在代码同步竞争中被阻塞的代码的堆栈跟踪信息。就是前面的阻塞概要信息。

mutex:在代码同步竞争中,获得过执行的代码的堆栈跟踪信息。

9. 如何为基于 HTTP 协议的网络服务添加性能分析接口?

(1) 在程序中导入net/http/pprof代码包。

     import _ "net/http/pprof"

(2) 启动网络服务并开始监听。

     log.Println(http.ListenAndServe("localhost:8082", nil))

(3) 在浏览器中访问  http://localhost:8082/debug/pprof  看到一个简约的网页

(4) 在/debug/pprof/ 这个URL路径下还有很多可用的子路径,包括:profile,trace,allocs、block、goroutine、heap、mutex、threadcreate。

(5) 返回二进制内容时,需要使用  go tool pprof 工具去查看。

    go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/diannao/13402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浏览器插件Video Speed Controller(视频倍速播放),与网页自身快捷键冲突/重复/叠加的解决办法

浏览器插件Video Speed Controller(视频倍速播放),与网站自身快捷键冲突/重复/叠加的解决办法 插件介绍问题曾今尝试的办法今日发现插件列表中打开Video Speed Controller的设置设置页面翻到下面,打开实验性功能。将需要屏蔽的原网…

网络工程师----第三十一天

DNS: DNS含义:DNS 是 Domain Name System(域名解析系统) 端口号:DNS为53(UDP) 域名的层次结构: 域名的分级: 域名服务器: 域名解析过程: 递归查…

PHP xdebug

使用场景 一台MAC上安装了phpstorm,虚拟机安装了对应的web程序,需要调试。 坑点,网上教程太多,不如看官网,需要按照xdebug版本来配置php.ini https://www.jetbrains.com/help/phpstorm/2023.3/configuring-xdebug.htm…

【Java】HOT100+代码随想录 动态规划(上)背包问题

目录 理论基础 一、基础题目 LeetCode509:斐波那契数 LeetCode70:爬楼梯 LeetCode746:使用最小花费爬楼梯 LeetCode62:不同路径 LeetCode63:不同路径ii LeetCode343:整数拆分 LeetCode96:不…

vue uniapp 小程序 判断日期是今天(显示时分秒)、昨天、本周的周几、超出本周显示年月日

效果图: util.js /*** 转换时间*/ const messageFormat (datetime) >{ let result "";let currentTime new Date();if(isToday(datetime)){result datetime.substring(11,16);}else if(isYesterday(datetime)){result "昨天";}else if(…

分层解耦-三层架构

分层解耦-三层架构 Controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据 service:业务逻辑层,处理具体的业务逻辑 dao:数据访问层(持久层),负…

python爬虫[简易版]

python爬数据[简易版] 对于每个网站的爬的原理基本是一样的,但是具体的代码写法的区别就在于爬的数据中解析出想要的数据格式: 以爬取有道词典中的图片为例: 第一步:打开网站,分析图片的数据源来自哪里, https://dict-subsidiary.youdao.com/home/content?invalid&pre…

操作系统磁盘管理类问题

例题:在磁盘上存储数据的排列方式会影响1/0服务的总时间。假设每个磁道被划分成10个物理块,每个物理块存放1个逻辑记录。逻辑记录R1,R2....R10存放在同一个磁道上,记录的排列顺序如下表所示: 假定磁盘的旋转速度为10ms/周&#xf…

VMware虚拟机-安装程序无法自动安装virtual machine......_windows server 2008 R2

系统版本:windows server 2008 R2 问题-安装程序无法自动安装virtual machine… 在使用虚拟机安装windows server 2008 R2系统中,安装VMware Tools工具安祖啊寄给你失败,提示安装程序无法自动安装virtual machine…,必须手动安装…

从源头到洞察:大数据时代的数据提取与分析实战指南

随着科技的飞速发展,大数据已经成为现代社会的核心驱动力之一。从商业决策到科学研究,从政策制定到个人生活,数据无处不在,影响着我们的每一个决策。然而,如何从海量的数据中提取有价值的信息,并转化为深刻…

List类

什么是 List 在集合框架中, List 是一个接口,继承自 Collection 。 Collection 也是一个接口 ,该接口中规范了后序容器中常用的一些方法,具体如下所示: List 中提供了好的方法,具体如下: List…

Conda 常用命令大全

Conda 常用命令大全 配置源conda配置清华源pip配置清华源pip配置阿里源 环境管理创建一个新的虚拟环境列出虚拟环境激活虚拟环境退出虚拟环境删除虚拟环境复制某个虚拟环境 conda包管理列出全部包安装包卸载包 pip包管理列出全部包安装包卸载包 其他命令查询 conda 版本查看环境…

python发票真伪查验开发文档、票据OCR、数电票查验

想象一下,只需一行行简洁的代码,复杂繁琐的发票审核工作瞬间变得井然有序。翔云发票查验开发文档详尽易懂,即便是Python新手也能迅速上手,搭建起自己的发票真伪查验系统。无论是纸质发票的扫描图像,还是电子发票的数据…

C语言详解:数组指针

数组指针是指针 int* p[10] 这是指针数组的写法 ,因为【】的优先级比*高, 所以为了解决优先级问题,加() int(* p)[10]&arr;//数组的地址要存起来 说明p是指针(首先与*结合)&#xff0c…

哈希表法快速求解最长连续序列 | 力扣128题详细解析

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣! 推荐:数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航: LeetCode解锁100…

Oracle 数据库 19c 选件和管理包 英文技术文档

都是英文的,点击链接可单独下载。点这里批量下载。 Database Options: 数据库选件或管理包数据表技术白皮书MultitenantData Sheet(12c)White PaperReal Application ClustersData Sheet(12c)White PaperActive Data GuardData Sheet(没找到)White Pap…

关于电源3(整流滤波电路)

整流滤波电路 框图 一共有四种整流电路 以下是自己参考别人的文章https://blog.csdn.net/zhuguanlin121/article/details/130653498?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171582622316800215096518%2522%252C%2522scm%2522%253A%252220140713.130102334…

jenkins配置不同版本nodeJS,保姆级叫你配置

问题描述:公司jenkins被改了nodejs版本适配其他项目导致以前的项目构建失败,原因就是nodejs版本太高或太低导致,这里教大家不去更改服务器默认版本,当需要特殊版本直接在jenkins里配置即可。 过程 1、安装nodeJS插件 1.1点击管…

Linux中的nproc命令

2024年5月15日,周三上午 nproc 是一个在类 Unix 系统中使用的命令行实用程序,用于返回系统上可用的处理器核心数量。这个数字通常比物理 CPU 核心的数量要少,因为它可能排除了超线程核心或热插拔核心。nproc 命令读取 /proc/cpuinfo 文件来获…

怎么把照片变小做头像?多种方法教你图片改尺寸

现在在社交媒体平台或者是社交软件上,我们经常会去更改头像来展示自己,但是有时候我们拍摄的照片太大无法直接用作头像,这时候就需要去修改图片尺寸,将图片改大小到合适的数值才能使用,那么如何快速的将图片改大小呢&a…