为了账号安全,请及时绑定邮箱和手机立即绑定

golang http 处理程序上下文

golang http 处理程序上下文

Go
呼唤远方 2021-11-15 17:07:59
我正在尝试使用以下代码了解 golang 中的变量范围。在此示例中,在 http 中调用页面将回显 uri 查询以及 Boltdb 中存储的值。问题是数据库驱动程序似乎没有在 http 处理程序上下文中正确运行:它不会向 stdout 或 http 请求打印任何内容。我期待它打印:他喜欢 <'uri query content'> 但更喜欢披萨(来自 bolt.db 驱动程序的数据)如何修复此代码?包主import (    "fmt"    "net/http"    "log"    "github.com/boltdb/bolt")var db bolt.DBfunc 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 回答

?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

我想我看到了你的错误。这个通常有点难以跟踪,因为它只是:在等号的前面。这基本上是一个作用域问题,因为您声明db为全局db变量,同时创建了一个作用域为您的主函数的变量。


您过去常常db, err := ...分配值,而不仅仅是=. :=将声明和推断类型。由于它也在进行声明,因此db您在main函数中使用的不是db您在全局范围内声明的。同时,处理程序仍在尝试使用db在全局范围内声明的 。下面的代码与您最初使用的代码相同,在代码中添加了一些注释以概述工作更改的内容。希望这可以帮助!


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)

}



查看完整回答
反对 回复 2021-11-15
  • 1 回答
  • 0 关注
  • 213 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信