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

相关文章

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

多重背包转换成0-1背包

http://acm.hdu.edu.cn/showproblem.php?pid=2191 多重背包特点: 一种物品有C个(既不是固定的1个,也不是无数个) 优化的方法: 运用神奇的二进制,进行物品拆分,转化成01背包 物品拆分,把13个相同的物品分成4组(1,2,4,6) 用这4组可以组成任意一个1~13之间的数! 原理:一个数总可以用2^

Java 连接Sql sever 2008

Java 连接Sql sever 2008 /Sql sever 2008 R2 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class TestJDBC

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

实例:如何统计当前主机的连接状态和连接数

统计当前主机的连接状态和连接数 在 Linux 中,可使用 ss 命令来查看主机的网络连接状态。以下是统计当前主机连接状态和连接主机数量的具体操作。 1. 统计当前主机的连接状态 使用 ss 命令结合 grep、cut、sort 和 uniq 命令来统计当前主机的 TCP 连接状态。 ss -nta | grep -v '^State' | cut -d " " -f 1 | sort |

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚: