0

次のコードを使用して、golang の変数スコープを理解しようとしています。この例では、http でページを呼び出すと、URI クエリが Boltdb に保存されている値と組み合わされてエコーされます。

問題は、データベース ドライバが http ハンドラ コンテキストで正しく動作していないように見えることです。標準出力にも http 要求にも何も出力しません。

私はそれが印刷されることを期待していました:

彼は <'uri query content'> が好きですが、ピザが好きです (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)

   }
4

1 に答える 1

2

私はあなたのバグを見たと思います。:これは通常、対等の前にあるため、追跡するのが少し困難です。dbグローバルとして宣言すると同時にdb、メイン関数にスコープされた変数を作成するため、基本的にスコープの問題でした。

db, err := ...の代わりに値を割り当てていました=:=型の宣言と推論の両方を行います。宣言も行っているため、関数でdb使用している は、グローバルスコープで宣言したものではありません。一方、ハンドラーは、グローバル スコープで宣言された を引き続き使用しようとしています。以下のコードは、最初に使用したものと同じコードですが、コード内にいくつかのコメントを追加して、作業上の変更点を概説しています。お役に立てれば!maindbdb

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)
}
于 2015-10-18T15:37:54.283 に答える