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)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥15 统计大规模图中的完全子图问题
  • ¥15 使用LM2596制作降压电路,一个能运行,一个不能
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题
  • ¥15 ogg dd trandata 报错
  • ¥15 高缺失率数据如何选择填充方式