Go 使用管道

Go 使用管道,go,Go,我正在探索Go,并试图建立一种使用通道的管道。我只想读取main()中的内容并将它们发送到process()进行处理,在本例中,只需将值打印到屏幕上 不幸的是,在下面的代码中,process()似乎从未从通道中读取,或者至少它没有打印任何内容;我做错了什么 package main import ( "fmt" ; "database/sql" ; _ "github.com/lib/pq" ; "time" ; "gopkg.in/redis.v3" )//; "strconv" ) ty

我正在探索Go,并试图建立一种使用通道的管道。我只想读取main()中的内容并将它们发送到process()进行处理,在本例中,只需将值打印到屏幕上

不幸的是,在下面的代码中,process()似乎从未从通道中读取,或者至少它没有打印任何内容;我做错了什么

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例程可以使用通道缓冲区上的内容。看看这个示例,这就是如何实现并行处理的方法。