Go 使用管道
我正在探索Go,并试图建立一种使用通道的管道。我只想读取main()中的内容并将它们发送到process()进行处理,在本例中,只需将值打印到屏幕上 不幸的是,在下面的代码中,process()似乎从未从通道中读取,或者至少它没有打印任何内容;我做错了什么Go 使用管道,go,Go,我正在探索Go,并试图建立一种使用通道的管道。我只想读取main()中的内容并将它们发送到process()进行处理,在本例中,只需将值打印到屏幕上 不幸的是,在下面的代码中,process()似乎从未从通道中读取,或者至少它没有打印任何内容;我做错了什么 package main import ( "fmt" ; "database/sql" ; _ "github.com/lib/pq" ; "time" ; "gopkg.in/redis.v3" )//; "strconv" ) ty
package main
import ( "fmt" ; "database/sql" ; _ "github.com/lib/pq" ; "time" ; "gopkg.in/redis.v3" )//; "strconv" )
type Record struct {
userId, myDate int
prodUrl string
}
func main(){
//connect to db
db, err := sql.Open(...)
defer db.Close()
//error check here...
//exec query
rows, err := db.Query("select userID,url,date from mytable limit 10")
defer rows.Close()
//error check here...
//create channel to buffer rows read
bufferChan := make(chan *Record,1000)
go process(bufferChan)
//iterate through results and send them to process()
row := new(Record)
for rows.Next(){
err := rows.Scan(&row.userId, &row.prodUrl, &row.myDate)
bufferChan <- row
fmt.Printf("row sent %v",row.userId)
}
}
//prints Record values
func process (buffer chan *Record) {
row := <- buffer
fmt.Printf("row received: %d %v %d ", row.userId,row.prodUrl,row.myDate)
}
主程序包
导入(“fmt”;“database/sql”;“github.com/lib/pq”;“time”;“gopkg.in/redis.v3”)/;“strconv”)
类型记录结构{
userId,myDate int
prodUrl字符串
}
func main(){
//连接到数据库
db,err:=sql.Open(…)
延迟db.Close()
//错误检查在这里。。。
//执行查询
行,err:=db.Query(“从mytable limit 10中选择用户ID、url、日期”)
延迟行。关闭()
//错误检查在这里。。。
//创建通道以缓冲读取的行
bufferChan:=制造(chan*记录,1000)
go流程(bufferChan)
//迭代结果并将其发送到process()中
行:=新(记录)
对于行。下一个(){
错误:=rows.Scan(&row.userId,&row.prodUrl,&row.myDate)
bufferChan主函数退出,因此整个程序结束。它应该等待处理结束。此外,处理函数应该使用range关键字在通道上循环
工作解决方案的脚手架如下所示:
package main
import "fmt"
func process(input chan int, done chan struct{}) {
for i := range input {
fmt.Println(i)
}
done <- struct{}{}
}
func main() {
input := make(chan int)
done := make(chan struct{})
go process(input, done)
for i := 1; i < 10; i++ {
input <- i
}
close(input)
<-done
}
主程序包
输入“fmt”
func进程(输入chan int,done chan struct{}){
对于i:=范围输入{
fmt.Println(一)
}
完成您的主函数退出,所以整个程序结束。它应该等待处理结束。此外,处理函数应该使用range关键字在通道上循环
工作解决方案的脚手架如下所示:
package main
import "fmt"
func process(input chan int, done chan struct{}) {
for i := range input {
fmt.Println(i)
}
done <- struct{}{}
}
func main() {
input := make(chan int)
done := make(chan struct{})
go process(input, done)
for i := 1; i < 10; i++ {
input <- i
}
close(input)
<-done
}
主程序包
输入“fmt”
func进程(输入chan int,done chan struct{}){
对于i:=范围输入{
fmt.Println(一)
}
donefunc进程不打印任何内容的原因是func main在for循环for行之后退出。下一步结束,从而退出程序。您需要做几件事
在for循环之后添加关闭调用,以指示结束向添加消息
缓冲通道,否则可能导致死锁。所以调用
关闭(缓冲区)
使用范围在func进程中的通道上迭代
将附加通道传递给进程,以了解它何时完成
那个干管可以等到过程结束
例如,请查看下面的代码段:
package main
import "fmt"
func main() {
bufferChan := make(chan int, 1000)
done := make(chan bool)
go process(bufferChan, done)
for i := 0; i < 100; i++ {
bufferChan <- i
}
close(bufferChan)
select {
case <-done:
fmt.Println("Done")
}
}
func process(c chan int, done chan bool) {
for s := range c {
fmt.Println(s)
}
done <- true
}
主程序包
输入“fmt”
func main(){
bufferChan:=make(chan int,1000)
完成:=制作(陈波)
go流程(缓冲区,完成)
对于i:=0;i<100;i++{
bufferChanfunc进程不打印任何内容的原因是func main在for循环for rows之后退出。下一步结束,从而退出程序。您需要做两件事
在for循环之后添加关闭调用,以指示结束向添加消息
缓冲通道,否则可能导致死锁。所以调用
关闭(缓冲区)
使用范围在func进程中的通道上迭代
将附加通道传递给进程,以了解它何时完成
那个干管可以等到过程结束
例如,请查看下面的代码段:
package main
import "fmt"
func main() {
bufferChan := make(chan int, 1000)
done := make(chan bool)
go process(bufferChan, done)
for i := 0; i < 100; i++ {
bufferChan <- i
}
close(bufferChan)
select {
case <-done:
fmt.Println("Done")
}
}
func process(c chan int, done chan bool) {
for s := range c {
fmt.Println(s)
}
done <- true
}
主程序包
输入“fmt”
func main(){
bufferChan:=make(chan int,1000)
完成:=制作(陈波)
go流程(缓冲区,完成)
对于i:=0;i<100;i++{
bufferChan我相信您正在寻找io.pipe()
go API,它在写入程序和读取器之间创建一个同步内存管道。这里没有缓冲。它可以用来连接需要io.reader
的代码和需要io.writer
的代码
在您的例子中,io.PipeWriter
是“从数据库读取值”的代码,“io.PipeReader”是“将值写入屏幕”的代码
这里是一个没有任何缓冲区的流数据示例,即字节.buffer
// Set up the pipe to write data directly into the Reader.
pr, pw := io.Pipe()
// Write JSON-encoded data to the Writer end of the pipe.
// Write in a separate concurrent goroutine, and remember
// to Close the PipeWriter, to signal to the paired PipeReader
// that we’re done writing.
go func() {
err := json.NewEncoder(pw).Encode(&v)
pw.Close()
}()
// Send the HTTP request. Whatever is read from the Reader
// will be sent in the request body.
// As data is written to the Writer, it will be available
// to read from the Reader.
resp, err := http.Post(“example.com”, “application/json”, pr)
参考:
我相信您正在寻找io.pipe()
go API,它在写入程序和读取器之间创建一个同步内存管道。这里没有缓冲区。它可以用于将需要io.reader
的代码与需要io.writer
的代码连接起来
在您的例子中,io.PipeWriter
是“从数据库读取值”的代码,“io.PipeReader”是“将值写入屏幕”的代码
这里是一个没有任何缓冲区的流数据示例,即字节.buffer
// Set up the pipe to write data directly into the Reader.
pr, pw := io.Pipe()
// Write JSON-encoded data to the Writer end of the pipe.
// Write in a separate concurrent goroutine, and remember
// to Close the PipeWriter, to signal to the paired PipeReader
// that we’re done writing.
go func() {
err := json.NewEncoder(pw).Encode(&v)
pw.Close()
}()
// Send the HTTP request. Whatever is read from the Reader
// will be sent in the request body.
// As data is written to the Writer, it will be available
// to read from the Reader.
resp, err := http.Post(“example.com”, “application/json”, pr)
参考:
谢谢,这是可行的,但发送和接收似乎是按顺序执行的,我理解错了吗?我的目标是让process()与main()并行执行,在可用时使用bufferChan通道中的数据,但似乎main()执行整个for()循环,然后才执行process()开始打印消息。是的,这是因为只有一个go例程可以使用通道bufferChan上的内容。看看这个示例,这是如何实现并行处理的。谢谢,这是可行的,但似乎发送和接收是按顺序执行的,我理解错了吗?我的目标是让process()执行与main()并行执行,在bufferChan通道中的数据可用时使用它,但main()似乎执行整个for()循环,然后才执行process()开始打印消息。是的,这是因为只有一个go例程可以使用通道缓冲区上的内容。看看这个示例,这就是如何实现并行处理的方法。