【问题标题】:Golang when trying to make method concurrent nothing returnsGolang尝试使方法并发时没有返回
【发布时间】:2016-07-11 03:58:45
【问题描述】:

我有一个从数据库返回 Json 的方法,它可以正常工作,但是当我尝试使其并发时,它不会返回任何内容,也不会给出任何错误。例如这是正确工作的方法

func Listing_Expiration(w http.ResponseWriter, r *http.Request)  {

        db,err := sql.Open("DB_Connect")

        if err != nil {
            log.Fatal(err)
            println(err)
        }



        var result string

        errr := db.QueryRow("select json_build_object('Expiration', array_to_json(array_agg(t))) from (select fullname,ad_end from profiles where id=32)t").Scan(&result)


        defer db.Close()
        switch {
        case errr != nil:
            log.Fatal(errr)


        }


        fmt.Fprintf(w,result)

}

上面的方法正常工作,数据返回到浏览器然后我尝试使这个方法异步

 func Listing_Expiration(w http.ResponseWriter, r *http.Request)  {
        go func(){

            db,err := sql.Open("DB_Connect")

            if err != nil {
                log.Fatal(err)
                println(err)
            }



            var result string

            errr := db.QueryRow("select json_build_object('Expiration', array_to_json(array_agg(t))) from (select fullname,ad_end from profiles where id=32)t").Scan(&result)


            defer db.Close()
            switch {
            case errr != nil:
                log.Fatal(errr)


            }


            fmt.Fprintf(w,result)

        }()
    }

上面的异步没有返回任何东西,我唯一改变的是我在方法中添加了 Go func() ,这样它就是异步的,其他的都是一样的。我检查了一下,数据库返回了相同的内容,只是不知道为什么异步没有将结果打印回浏览器。

【问题讨论】:

    标签: go


    【解决方案1】:

    net/http 服务器在处理程序返回时完成响应。处理程序返回后写入响应的任何内容都将被忽略。

    处理函数Listing_Expiration在匿名函数执行fmt.Fprintf(w,result)之前返回。

    要解决此问题,请使用sync.WaitGroup

    func Listing_Expiration(w http.ResponseWriter, r *http.Request)  {
      var wg sync.WaitGroup
      wg.Add(1)
      go func(){
        defer wg.Done()
        // same code here as in question
      }()
      wg.Wait()
    }
    

    net/http 服务器为每个连接启动一个 goroutine,并在这些 goroutine 中运行处理程序。如果问题中的代码是完整的处理程序,则没有理由启动另一个 goroutine。

    【讨论】:

    • 完美,我现在要阅读文档,所以基本上每当我使用打印到浏览器的 GoRoutine 时,总是使用 WaitGoup 对吗?
    • 如果应用程序写入来自 goroutine 的响应,那么应用程序必须做一些事情来确保处理程序等待 goroutine。 WaitGroups 是一种方便的方法。也可以使用通道。为了避免响应编写器的竞争,通常最好从处理程序的 goroutine 写入响应。在此示例中这不是问题,但请考虑如果应用异步运行两个查询会发生什么。
    • 非常感谢完美的解释我现在将重写来自 Goroutine 处理程序的响应。
    猜你喜欢
    • 2017-08-15
    • 2017-05-07
    • 2022-12-18
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多