2015-10-18 34 views
1

我想通過以下代碼瞭解golang中的變量作用域。 在這個例子中,在http頁面中調用將回顯uri查詢與Boltdb中存儲的值的組合。golang http處理器上下文

問題是數據庫驅動程序在http處理程序上下文中似乎沒有正確運行:它不會向stdout或http請求輸出任何內容。

我期待它打印:

他愛< 'URI查詢內容'>但喜歡比薩餅(從bolt.db驅動程序數據)

如何解決這個代碼? 包主

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) 

    } 

回答

3

我想我看到你的bug。這一點通常有點難以追蹤,因爲它只是在等號前面的:。這基本上是一個範圍問題,因爲您將db聲明爲全局變量,同時創建一個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) 
} 
+0

哇,你是我今天的救星! – pinkvoid