golang并发编程-01多进程编程-02管道

1 概述

概念:是一种半双工的(或者说单向的)通讯方式。它只能被用于父进程与子进程以及同祖先的子进程之间的通讯。
优点:简单
缺点:只能单向通讯以及对通讯双方关系上的严格限制

2 cmd的管道

2.1 示例1 (利用管道输出命令结果)

package hello

import (
	"bytes"
	"fmt"
	"io"
	"os/exec"
)

func Hello() {
    //创建一个命令行
	cmd0 := exec.Command("PowerShell.exe","echo","-n","liuBei guanYu zhangFei")
	//创建一个能够获取此命令的输出的管道
	stdout0, err := cmd0.StdoutPipe()
	if err != nil{
		return
	}
	//start方法启动执行命令
	if err := cmd0.Start(); err != nil {
		fmt.Printf("Error: The command No.0 can not be startup: %s\n", err)
		return
	}
	//定义一个缓存区
	var outputBuf0 bytes.Buffer
	for {
	    //定义一个二进制切片tempOutput 来接收管道stdout0的数据
		tempOutput := make([]byte, 5)
		n, err := stdout0.Read(tempOutput)
		if err != nil {
		    //如果收到错误是结尾就跳出循环。
			if err == io.EOF {
				break
			} else {
				fmt.Printf("Error: Can not read data from the pipe: %s\n", err)
				return
			}
		}
		//如果管道中有数据,则写入缓存(outputBuf0)
		if n > 0 {
			outputBuf0.Write(tempOutput[:n])
		}
	}
    //从缓存中读数
	fmt.Printf("%s\n", outputBuf0.String())
}

2.2 示例2(两条命令间的交互)

package hello

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os/exec"
)
func Apipe02(){
	cmd1 := exec.Command("PowerShell.exe","ls")
	cmd2 := exec.Command("PowerShell.exe","findstr.exe", "hello")

	//在cmd1代表的命令之上建立一个输出管道
	stdout1, err := cmd1.StdoutPipe()
	if err != nil {
		fmt.Printf("Error: Can not obtain the stdout pipe for command: %s\n", err)
		return
	}
	if err := cmd1.Start(); err != nil {
		fmt.Printf("Error: The command can not be startup: %s\n", err)
		return
	}

	//创建一个来自cmd1输出管道(stdout1)的输入管道outputBuf1
	outputBuf1 := bufio.NewReader(stdout1)

	//建立cmd2的输出管道
	stdin2,err := cmd2.StdinPipe()
	if err != nil {
		fmt.Printf("Error: Can not obtain the stdin pipe for command: %s\n", err)
		return
	}
	//cmd1输出管道(stdout1)的输入管道(outputBuf1)连接到cmd2的输出管道
	_,err = outputBuf1.WriteTo(stdin2)

	//定义一个缓存
	var outputBuf2 bytes.Buffer
	//将cmd2的标准输出指向缓存
	cmd2.Stdout = &outputBuf2
	//执行cmd2
	if err := cmd2.Start(); err != nil {
		fmt.Printf("Error: The command can not be startup: %s\n", err)
		return
	}
	//关闭cmd2的输出管道
	err = stdin2.Close()
	if err != nil {
		fmt.Printf("Error: Can not close the stdio pipe: %s\n", err)
		return
	}

	//等待cmd2 写完再去读
	if err := cmd2.Wait(); err != nil {
		fmt.Printf("Error: Can not wait for the command: %s\n", err)
		return
	}
	//读缓存
	fmt.Printf("%s\n", outputBuf2.String())
}

3. 内存管道

  • 创建管道
reader, writer := io.Pipe()
  • 写入
 n,_err := writer.Write([]byte("hello"))

返回值n 是输入的字节数

  • 读取

创建一个切片以接收数据

	buffer := make([]byte, 100)
	n,err = reader.Read(buffer)
  • 示例
	reader, writer := io.Pipe()
	// 创建携程给writer
	go func() {
		_,err = writer.Write([]byte("hello"))
		if err != nil{
			return
		}
		defer writer.Close()
	}()

	buffer := make([]byte, 100)
	_,err = reader.Read(buffer)
	if err != nil {
		return err
	}
	fmt.Println(string(buffer))
	return nil

4. os管道

reader, writer, err := os.Pipe()

和内存管道用法相同


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玄德公笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值