Go实现将io.Writer转换成字符串

 更新时间:2024年05月05日 10:23:44   作者:zhonguncle  
golang中提供了各种类型之间的转换方法,其中,将其他类型转换为字符串类型是常见的操作,本文主要介绍了Go实现将io.Writer转换成字符串,具有一定的参考价值,感兴趣的可以了解一下

假设我们需要在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.Buffer
	r, 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转换成字符串的文章就介绍到这了,更多相关Go io.Writer转换成字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Go语言如何使用xorm实现读取mysql

    详解Go语言如何使用xorm实现读取mysql

    xorm是go语言的常用orm之一,可以用来操作数据库。本文就来和大家聊聊Go语言如何使用xorm实现读取mysql功能,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-11-11
  • Golang使用channel实现数据汇总的方法详解

    Golang使用channel实现数据汇总的方法详解

    这篇文章主要为大家详细介绍了在并发编程中数据汇总的问题,并探讨了在并发环境下使用互斥锁和通道两种方式来保证数据安全性的方法,需要的可以参考一下
    2023-05-05
  • golang gorm的预加载及软删硬删的数据操作示例

    golang gorm的预加载及软删硬删的数据操作示例

    这篇文章主要介绍了golang gorm的预加载及软删硬删的数据操作示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • logrus hook输出日志到本地磁盘的操作

    logrus hook输出日志到本地磁盘的操作

    这篇文章主要介绍了logrus hook输出日志到本地磁盘的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Golang 实现 Redis系列(六)如何实现 pipeline 模式的 redis 客户端

    Golang 实现 Redis系列(六)如何实现 pipeline 模式的 redis 客户端

    pipeline 模式的 redis 客户端需要有两个后台协程负责 tcp 通信,调用方通过 channel 向后台协程发送指令,并阻塞等待直到收到响应,本文是使用 golang 实现 redis 系列的第六篇, 将介绍如何实现一个 Pipeline 模式的 Redis 客户端。
    2021-07-07
  • 深入理解golang chan的使用

    深入理解golang chan的使用

    本文主要介绍了golang chan的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • VSCode Golang dlv调试数据截断问题及处理方法

    VSCode Golang dlv调试数据截断问题及处理方法

    这篇文章主要介绍了VSCode Golang dlv调试数据截断问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • go语言工程结构

    go语言工程结构

    这篇文章主要简单介绍了go语言工程结构,对于我们学习go语言很有帮助,需要的朋友可以参考下
    2015-01-01
  • Golang信号处理及如何实现进程的优雅退出详解

    Golang信号处理及如何实现进程的优雅退出详解

    这篇文章主要给大家介绍了关于Golang信号处理及如何实现进程的优雅退出的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-03-03
  • Go语言实现枚举的示例代码

    Go语言实现枚举的示例代码

    本文主要介绍了Go语言实现枚举的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01

最新评论