11

sql.Open() は *sql.DB 型の変数を返します

データベース呼び出しを行う必要がある他の 10 個の関数を呼び出す関数があります。

次のほうがより正確/効率的ですか?

  • *sql.DB ポインターをすべての関数に送信するか、または
  • 各関数で新しい *sql.DB オブジェクトを作成します

意味

func DoLotsOfThings() {
    db, _ := sql.Open()
    defer db.Close()
    DoTask1(db)
    DoTask2(db)
}

また

func DoLotsOfThings() {
    DoTask1()
    DoTask2()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

私が質問している理由は、現在各関数にポインターを送信していて、ドライバーが壊れているように見えるためです。私はhttp://code.google.com/p/odbcを使用しています。これにより、各関数には独自の関数が必要であり、ドライバーの内部構造に依存できると信じています。

編集

RE ドライバーの破損。交通量の多い環境でのみ発生します。そして、それは、たとえば10分ほど経った後にのみ発生します。これは、ドライバーの使用を停止させるある種のメモリリークがあると私に信じさせます。ただし、*sql.DB のすべてのインスタンスに対して db.Close() を延期するため、この問題を解決するために他に何ができるかわかりません。

andybalholm は、接続プールは内部で処理されると述べていますが、これは正確なようです。これは、sql.Open() を呼び出したときではなく、何かを実行しようとした後にのみ中断するためです。

Go アプリを実行したままにしておくと、どのような SQL クエリも実行できなくなりますが、MSSQL に接続してクエリを実行する他の Go テストを個別に実行しようとすると、動作します。

4

2 に答える 2

20

をグローバルに宣言してvar db *sql.DBから、コード全体で再利用します。以下に例を示します (簡略化)。

var db *sql.DB

func DoLotsOfThings() {
    DoTask1(db)
    DoTask2(db)
}

func main() {
  db, _ = sql.Open() # or whatever you use
  defer db.Close()
  DoLotsOfThings()
}

グローバルに宣言することには、 SetMaxIdleConns (接続プール サイズの調整) やアプリケーション全体での SQL ステートメントの準備*sql.DBなど、いくつかの追加の利点もあります。

于 2013-11-14T12:52:42.710 に答える
8

あちこちでデータベース接続を開く必要はありません。database/sql パッケージは内部で接続プールを行い、必要に応じて接続を開いたり閉じたりしながら、同時に使用できる単一の接続の錯覚を提供します。

おそらく、ドライバーの破損の原因を別の場所で探す必要があります。それに関するいくつかの詳細は、人々が何が起こっているのかをより簡単に理解できるようにするでしょう.

于 2013-11-14T19:23:40.803 に答える