dtv55860 2015-10-18 14:42
浏览 39
已采纳

golang http处理程序上下文

I'm trying to understand variable scopes in golang with the following code. In this example, calling in http a page will echo the uri query combined with a stored value in Boltdb.

The problem is that the database driver doesn't seem to run correctly in the http handler context: it doesn't print anything to stdout nor to the http request.

I was expecting it to print :

He's loving <'uri query content'> but prefers pizza (data from bolt.db driver)

How to fix this code? package main

import (
    "fmt"
    "net/http"
    "log"
    "github.com/boltdb/bolt"
)

var db bolt.DB

func handler(w http.ResponseWriter, r *http.Request) {
    dberr := db.Update(func(tx *bolt.Tx) error {
    log.Println("here")
        b := tx.Bucket([]byte("MyBucket"))
            loving := b.Get([]byte("loving"))
        log.Printf("He's loving %s but prefers %s",r.URL.Path[1:], string(loving))
            fmt.Fprintf(w,"He's loving %s but prefers %s",r.URL.Path[1:], string(loving) )
        return nil
    })
    if dberr != nil {
        fmt.Errorf("db update: %s", dberr)
    }
    log.Printf("Finished handling")
}

func main() {

    db, err := bolt.Open("my.db", 0600, nil)
    if err != nil {
        log.Fatal(err)
    }else{
        log.Println("database opened")
    }
    dberr := db.Update(func(tx *bolt.Tx) error {
        b, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
        if err != nil {
        return fmt.Errorf("create bucket: %s", err)
        }
        err2 := b.Put([]byte("loving"), []byte("pizza"))
        if err2 != nil {
        return fmt.Errorf("put loving: %s", err2)
        }
        loving := b.Get([]byte("loving"))
        log.Printf("He's loving %s", string(loving))
        return nil
    })

        if dberr != nil {
        fmt.Errorf("db update: %s", err)
        }
    defer db.Close()

    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)

   }
  • 写回答

1条回答 默认 最新

  • douhuan1648 2015-10-18 15:37
    关注

    I think I see your bug. This one is usually a little difficult to track because its just the : in front of the equals. It was basically a scoping issue because you declared db as a global while at the same time creating a db variable that was scoped to your main function.

    You used db, err := ... to assign the values instead of just =. := will both declare and infer the type. Since its also doing declaration, the db you're using in the main function is not the db you have declared in the global scope. Meanwhile the handler is still attempting to use the db that was declared in the global scope. The below code is the same code as you initially had with a few comments in the code to outline what the working changes are. Hope this helps!

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
    
        "github.com/boltdb/bolt"
    )
    
    var db *bolt.DB // this is going to be a pointer and is going to be nil until its set by the main function
    
    func handler(w http.ResponseWriter, r *http.Request) {
        dberr := db.Update(func(tx *bolt.Tx) error {
            log.Println("here")
            b := tx.Bucket([]byte("MyBucket"))
            loving := b.Get([]byte("loving"))
            log.Printf("He's loving %s but prefers %s", r.URL.Path[1:], string(loving))
            fmt.Fprintf(w, "He's loving %s but prefers %s", r.URL.Path[1:], string(loving))
            return nil
        })
        if dberr != nil {
            fmt.Errorf("db update: %s", dberr)
        }
        log.Printf("Finished handling")
    }
    
    func main() {
        var err error                           // this will have to be declared because of the next line to assign db the first value returned from `bolt.Open`
        db, err = bolt.Open("my.db", 0600, nil) // notice that this has changed and is no longer `db, err := ...` rather its `db, err = ...`
        if err != nil {
            log.Fatal(err)
        } else {
            log.Println("database opened")
        }
        dberr := db.Update(func(tx *bolt.Tx) error {
            b, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
            if err != nil {
                return fmt.Errorf("create bucket: %s", err)
            }
            err2 := b.Put([]byte("loving"), []byte("pizza"))
            if err2 != nil {
                return fmt.Errorf("put loving: %s", err2)
            }
            loving := b.Get([]byte("loving"))
            log.Printf("He's loving %s", string(loving))
            return nil
        })
    
        if dberr != nil {
            fmt.Errorf("db update: %s", err)
        }
        defer db.Close()
    
        http.HandleFunc("/", handler)
        http.ListenAndServe(":3000", nil)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度