Go中如何将io.Writer转换成字符串(将两个管道连接的exec.Command输出的标准输出获取成字符串)

本文主要是介绍Go中如何将io.Writer转换成字符串(将两个管道连接的exec.Command输出的标准输出获取成字符串),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

假设我们需要在Go中运行下面的命令:

PS -A | grep wget

这里需要写成两个exec.Command,如下,第一个命令为cmd,第二个为cmd2

cmd := exec.Command("PS", "-A")
cmd2 := exec.Command("grep", "wget")

然后使用管道连接二者的标准输出和标准输入,需要注意第一个命令cmd的标准输出应该使用cmd.StdoutPipe(),而不是Stdout,如下(忽略了错误err和其处理):

cmd2.Stdin, _ = cmd.StdoutPipe()

因为cmd.Stdout是一个io.Writer,是一个写入器,因为这个输出是要写入某些地方的。而同理,cmd2.Stdin是一个io.Reader,是一个读取器,用来读取一些地方的内容。二者直接赋值的话会出现类型不匹配的错误。所以需要使用StdoutPipe()函数,这个函数会返回一个io.Reader。(这里比较绕,所以可能需要想一下)

在获取了输出之后,需要将其转换成字符串的话,可以使用bytes.Buffer来获取cmd2.Stdout的标准输出(记住这是个io.Writer),然后再转换成字符串。

我们是是无法直接将io.Writer直接写入到bytes.Buffer之中的,你可能会说bytes.Buffer不是有两个方法ReadFromWriteTo吗?

前者只能读取io.Reader的,后者只能写入io.Writer,所以我们需要一个管道来将io.Writer转换成io.Reader,然后才能读取或复制其内容。而这个转换就是再使用一次管道,如下:

var buf bytes.Buffer
r, w, _ := os.Pipe()
cmd2.Stdout = w
go buf.ReadFrom(r)

这里buf.ReadFrom(r)必须使用 goroutine,也就是让这个代码并行运行,所以在前面加上go

这里的go buf.ReadFrom(r)也可以使用go io.Copy(&buf, r)替代,效果一样。

因为命令执行的顺序是先启动cmd2,然后运行cmdcmd运行完之后,数据流通过管道传递给cmd2cmd2再运行。不然cmd运行的时候的标准输出是空的,就会一直等。

buf.ReadFrom(r)cmd2也是同理,不过由于这是行代码,无法使用start启动它,所以并行就行了。

接下来的命令如下:

cmd2.Start()
cmd.Run()
cmd2.Wait()

这里就是前面说的流程:cmd2启动,运行cmd,让cmd2等待cmd的输出。

需要注意一点:go buf.ReadFrom(r)其实可以放在上面代码中,除了最后一行之外的任何地方。之所以不能放在最后是因为这时候都运行完了,再读取就是空的了。

然后将其转换成字符串:

str := buf.String()

打印看看:

fmt.Println("123" + str + "123")

之所以要前后都加上"123"是为了避免调试的时候把输出到标准输出文件的内容当成这里打印的。

结果如下:

% go run main.go
12360651 ttys010    0:00.00 grep wget
123

这里分成两行是因为获取的时候grep wget后面有个\n,这里看不出来,如果%#v格式化打印就能看到了。

完整代码如下:

func main() {cmd := exec.Command("PS", "-A")cmd2 := exec.Command("grep", "wget")cmd2.Stdin, _ = cmd.StdoutPipe()var buf bytes.Bufferr, w, _ := os.Pipe()cmd2.Stdout = w// 下面这行代码可以替换为:go io.Copy(&buf, r)go buf.ReadFrom(r)cmd2.Start()cmd.Run()cmd2.Wait()str := buf.String()fmt.Println("123" + str + "123")
}

希望能帮到有需要的人~

这篇关于Go中如何将io.Writer转换成字符串(将两个管道连接的exec.Command输出的标准输出获取成字符串)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/963937

相关文章

5分钟获取deepseek api并搭建简易问答应用

《5分钟获取deepseekapi并搭建简易问答应用》本文主要介绍了5分钟获取deepseekapi并搭建简易问答应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1、获取api2、获取base_url和chat_model3、配置模型参数方法一:终端中临时将加

使用TomCat,service输出台出现乱码的解决

《使用TomCat,service输出台出现乱码的解决》本文介绍了解决Tomcat服务输出台中文乱码问题的两种方法,第一种方法是修改`logging.properties`文件中的`prefix`和`... 目录使用TomCat,service输出台出现乱码问题1解决方案问题2解决方案总结使用TomCat,

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

VScode连接远程Linux服务器环境配置图文教程

《VScode连接远程Linux服务器环境配置图文教程》:本文主要介绍如何安装和配置VSCode,包括安装步骤、环境配置(如汉化包、远程SSH连接)、语言包安装(如C/C++插件)等,文中给出了详... 目录一、安装vscode二、环境配置1.中文汉化包2.安装remote-ssh,用于远程连接2.1安装2

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

基于Go语言实现一个压测工具

《基于Go语言实现一个压测工具》这篇文章主要为大家详细介绍了基于Go语言实现一个简单的压测工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理客户端模块Http客户端处理Grpc客户端处理Websocket客户端

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat