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()
和内存管道用法相同