2017-02-16 143 views
2

我是Golang的新手,並且是一般編譯的靜態類型編程。我之前的所有經驗都與Python有關。當我終於讓我的腦海圍繞許多先前對我來說陌生的概念(垃圾收集,指針,範圍)時,這種範式轉變既令人沮喪(程序很少編譯),也帶來了回報。Golang,指針,函數

有人可以在概念層面向我解釋爲什麼這個程序不會編譯和解決它的語法?我只是想查詢數據庫並打印結果:

package main 

import (
    "database/sql" 
    "log" 

    _ "github.com/denisenkom/go-mssqldb" 
) 

func main() { 

    db, err := sql.Open("sqlserver", "odbc:server=myServer;user id=myName;password=myPassword;") 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer db.Close() 

    q() 
} 

func q() { 

    var (
     id int 
     name string 
    ) 

    rows, err := db.Query("SELECT id, name FROM myTable") 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer rows.Close() 

    for rows.Next() { 
     err := rows.Scan(&id, &name) 

     if err != nil { 
      log.Fatal(err) 
     } 
     log.Println(id, name) 
    } 
    err = rows.Err() 
    if err != nil { 
     log.Fatal(err) 
    } 

} 

我得到的錯誤是:

undefined: db in db.Query

的查詢工作,當我把裏面的邏輯Q()在主函數中 - 我假設這是因爲函數具有「本地」範圍(是否是正確的術語?),我需要像在主函數中那樣定義db對象。

如果是這種情況 - 我如何運行q()函數而不重複建立數據庫連接?這是「指針」進來嗎?另外,我還是不確定的,以什麼&符號在這裏做的:

err := rows.Scan(&id, &name) 

感謝

+1

如何有關傳遞'db'作爲參數傳遞給'Q()'?這將工作。 –

+0

這對python範圍規則無效,你在'main'中定義'db',但是試圖在'q'中引用它。 – JimB

+0

相關:https://stackoverflow.com/questions/40587008/how-do-i-handle-opening-closing-db-connection-in-a-go-app – JimB

回答

3

db VAR在main FUNC範圍界定,所以您的q FUNC不「看」它。您必須將其作爲指向q方法的指針傳遞。類似的東西:

func q(db *sql.DB) { 
    ... 
} 

db VAR在main已經是一個指針sql.DB結構,所以你只需要做q(db)呼叫main FUNC鍵,它會工作。

+1

繼續前進!你做得很好! Go是你的新世界,因此一開始就會感到困惑嘗試 –

+1

請刪除「參考」一詞:Go中沒有提及。 – kostix

2

正如其他人提到的,問題是變量db在函數main中聲明,並且您試圖訪問q函數中的該變量。您有兩個選項來解決這個問題:

1)聲明變量db像這樣的主要功能之外的全局變量:

正如其他人所提到的,問題是變量db在功能main聲明,您正嘗試訪問q函數中的該變量。您有兩個選項來解決這個問題:

1)聲明變量db爲主要功能之外的全局變量是這樣的:

package main 

import (
"database/sql" 
"log" 
_ "github.com/denisenkom/go-mssqldb" 
) 

var db *sql.DB 

func main() { 

db, err = sql.Open("sqlserver", "odbc:server=myServer;user id=myName;password=myPassword;") 
. 
. 
. 
. 

重要的是要注意的是分配(的=代替:= )運算符用於爲全局變量賦值。因爲如果使用短變量聲明:=那麼它會創建一個本地變量db

2)可以傳遞db指針作爲參數傳遞給該函數q這樣的:

package main 

import (
    "database/sql" 
    "log" 
    _ "github.com/denisenkom/go-mssqldb" 
) 
func main() { 

    db, err := sql.Open("sqlserver", "odbc:server=myServer;user id=myName;password=myPassword;") 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer db.Close() 

    q(db) 
} 

func q(db *sql.DB) { 

    var (
     id int 
     name string 
    ) 
. 
. 
. 
.