Jestem nowy w Golangowi i skompilowany, statycznie typowo programowaniu ogólnie. Wszystkie moje wcześniejsze doświadczenie było z Pythonem.

Ta zmiana paradygmatu była zarówno frustrująca (programy rzadko kompilują) i satysfakcjonująca, ponieważ w końcu zdobywam głowę wokół wielu koncepcji, które były wcześniej obceniowe (zbieranie śmieci, wskaźniki, zakres).

Czy ktoś może mi wyjaśnić na poziomie koncepcyjnym, dlaczego ten program nie skompiluje i składnia do naprawienia? Po prostu próbuję zapytać o db i wydrukować wyniki:

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)
    }

}

Pojawia się błąd:

undefined: db in db.Query

Zapytanie działa, gdy umieściłem logikę w Q () w głównej funkcji - Zakładam, że jest to dlatego, że funkcje mają "lokalny" zakres (czy to prawidłowa terminologia?) I muszę zdefiniować obiekt DB, który miałem główna funkcja.

Jeśli tak jest - jak uruchomić funkcję Q () bez powtarzania się w tworzeniu połączenia DB? Czy to właśnie wchodzi "wskaźniki"? Nadal jestem niepewny, co robią tutaj ampersands:

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

Dzięki

2
mk8efz 17 luty 2017, 01:22

2 odpowiedzi

Najlepsza odpowiedź

db var jest zdefiniowany w main Zakres func, więc twoja q func nie "Zobacz to". Musisz przejść jako wskaźnik do metody {x3}}. Coś w tym stylu:

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

Twój db var w main jest już wskaźnikiem do sql.DB struktura, więc po prostu musisz zrobić q(db) call in main Func i to będzie działać.

3
Tarsis Azevedo 20 luty 2017, 22:26

Jak wspomniano inni, problem jest zmienna db jest zadeklarowany w funkcji main i próbujesz uzyskać dostęp do tej zmiennej w q funkcji. Masz dwie opcje, aby rozwiązać ten problem:

1) deklaruj zmienną db jako zmienna globalna poza funkcją główną taką:

Jak wspomniano inni, problem jest zmienna db jest zadeklarowany w funkcji main i próbujesz uzyskać dostęp do tej zmiennej w q funkcji. Masz dwie opcje, aby rozwiązać ten problem:

1) deklaruj zmienną db jako zmienna globalna poza funkcją główną taką:

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;")
.
.
.
.

Ważną rzeczą do powiadomienia jest przypisanie (= zamiast operatora :=) używany do przypisywania wartości do zmiennej globalnej. Ponieważ jeśli używasz krótkiej deklaracji zmiennej :=, a następnie utworzyłoby zmienną lokalną db.

2) Możesz przekazać wskaźnik db jako parametr do funkcji q w ten sposób:

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
    )
.
.
.
.
2
deLta 16 luty 2017, 23:54