我正在尝试使用以下代码来理解 golang 中的变量范围。 在此示例中,在 http 中调用页面将回显 uri 查询以及 Boltdb 中存储的值。
问题是数据库驱动程序似乎没有在 http 处理程序上下文中正确运行:它没有向标准输出或 http 请求打印任何内容。
我期待它打印出来:
He's loving <'uri query content'> but prefers pizza (data from bolt.db driver)
如何修复此代码? 主包
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)
}
最佳答案
我想我看到了你的错误。这通常有点难以跟踪,因为它只是等号前面的 :
。这基本上是一个作用域问题,因为您将 db
声明为全局变量,同时创建了一个作用域为 main 函数的 db
变量。
您使用 db, err := ...
来分配值,而不仅仅是 =
。 :=
将声明和推断类型。由于它也在进行声明,因此您在 main
函数中使用的 db
不是您在全局范围内声明的 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)
}
关于golang http处理程序上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33199261/