go语言快速入门 IPC之管道通信 8

本文通过实例演示了如何在Go语言中使用管道进行进程间通信,包括调用操作系统命令、创建输出管道、连接管道以及使用grep命令过滤输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                       

熟悉Unix/C编程的应该对IPC也非常的熟悉,多进程之间的通信主要的手段有管道/信号量/共享内存/Socket等,而管道作为父子进程间进行少量数据传递的有效手段也得到了广泛的应用,在这篇文章中我们来看一下go语言中如何使用管道进行进程进行通信。

管道的使用

在linux下,管道被非常广泛地使用,一般在编程中我们实现了popen等的应用即可提供管道功能。而在命令行中使用地也非常多,|就是最为典型的管道的应用例子。shell会为|符号两侧的命令各创建一个脚本,将左侧的输出管道与右侧的输入管道进行连接,可以进行单向管道通信。
比如我们使用go env来确认go语言的环境变量,然后使用grep从中确认出GOROOT环境变量的值一般会如下这样做

[root@liumiaocn goprj]# go env |grep GOROOTGOROOT="/usr/local/go"[root@liumiaocn goprj]#
  
  • 1
  • 2
  • 3

实现的过程其实go env会启动一个进程, 而grep命令也会产生一个进程,grep的进程会在go env的标准输出中进行检索GOROOT的行的信息然后显示出来,而负责这两个进程间的通信的正是管道。
在c语言中,我们需要父进程中进行fork以及对父进程的基本信息进行处理,同时初期化连接的管道信息从而实现管道通信。接下来,我们来看一下在go语言中是如何实现的

调用操作系统命令

为了方便演示,我们使用标准库os中的api以调用操作系统的命令并在此基础上建立用于通信的管道

例子代码

[root@liumiaocn goprj]# cat basic-ipc-pipe.gopackage mainimport "fmt"import "os/exec"func main() {        //create cmd        cmd_go_env := exec.Command("go", "env")        //cmd_grep:=exec.Command("grep","GOROOT")        stdout_env, env_error := cmd_go_env.StdoutPipe()        if env_error != nil {                fmt.Println("Error happened about standard output pipe ", env_error)                return        }        //env_error := cmd_go_env.Start()        if env_error := cmd_go_env.Start(); env_error != nil {                fmt.Println("Error happened in execution ", env_error)                return        }        a1 := make([]byte, 1024)        n, err := stdout_env.Read(a1)        if err != nil {                fmt.Println("Error happened in reading from stdout", err)        }        fmt.Printf("Standard output of go env command: %s", a1[:n])}[root@liumiaocn goprj]#
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

执行结果

[root@liumiaocn goprj]# go run basic-ipc-pipe.goStandard output of go env command: GOARCH="amd64"GOBIN=""GOEXE=""GOHOSTARCH="amd64"GOHOSTOS="linux"GOOS="linux"GOPATH=""GORACE=""GOROOT="/usr/local/go"GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"CC="gcc"GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build142715013=/tmp/go-build -gno-record-gcc-switches"CXX="g++"CGO_ENABLED="1"[root@liumiaocn goprj]#
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

管道连接

通过调用exec.Start启动一个进程,通过StdoutPipe将此调用的输出管道也创建了出来,在这里,我们读取了此输出的信息,确实是go env命令的标准输出,接下来要做的事情就是将此输出的管道与grep命令的进程进行连接了。我们将上面的代码进一步充实:

例子代码

[root@liumiaocn goprj]# cat basic-ipc-pipe.gopackage mainimport "fmt"import "os/exec"import "bufio"import "bytes"func main() {        //create cmd        cmd_go_env := exec.Command("go", "env")        cmd_grep := exec.Command("grep", "GOROOT")        stdout_env, env_error := cmd_go_env.StdoutPipe()        if env_error != nil {                fmt.Println("Error happened about standard output pipe ", env_error)                return        }        //env_error := cmd_go_env.Start()        if env_error := cmd_go_env.Start(); env_error != nil {                fmt.Println("Error happened in execution ", env_error)                return        }        /*                a1 := make([]byte, 1024)                n, err := stdout_env.Read(a1)                if err != nil {                        fmt.Println("Error happened in reading from stdout", err)                        return                }                fmt.Printf("Standard output of go env command: %s", a1[:n])        */        //get the output of go env        stdout_buf_grep := bufio.NewReader(stdout_env)        //create input pipe for grep command        stdin_grep, grep_error := cmd_grep.StdinPipe()        if grep_error != nil {                fmt.Println("Error happened about standard input pipe ", grep_error)                return        }        //connect the two pipes together        stdout_buf_grep.WriteTo(stdin_grep)        //set buffer for reading        var buf_result bytes.Buffer        cmd_grep.Stdout = &buf_result        //grep_error := cmd_grep.Start()        if grep_error := cmd_grep.Start(); grep_error != nil {                fmt.Println("Error happened in execution ", grep_error)                return        }        err := stdin_grep.Close()        if err != nil {                fmt.Println("Error happened in closing pipe", err)                return        }        //make sure all the infor in the buffer could be read        if err := cmd_grep.Wait(); err != nil {                fmt.Println("Error happened in Wait process")                return        }        fmt.Println(buf_result.String())}[root@liumiaocn goprj]#
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

内容非常简单,无需过多解释,唯一需要注意的就是上一个例子中为了确认中间信息,读出管道的信息,但是此处读完了,输入管道就读不到了,所以注释掉了才能正常执行

执行结果

[root@liumiaocn goprj]# go run basic-ipc-pipe.goGOROOT="/usr/local/go"[root@liumiaocn goprj]#
  
  • 1
  • 2
  • 3
  • 4

从这里可以看出与go env |grep GOROOT是一样的结果。

总结

本文通过模拟非常简单的管道在go中实现的例子,解释了go语言中匿名管道的使用方式,当然和unix/c一样,go也支持命名管道,通过os.Pipe()即可轻松实现,基本原理均类似,在此不再赘述。

           

给我老师的人工智能教程打call!http://blog.youkuaiyun.com/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值