Результаты SQL-запроса попадают во вложенную структуру, используя Golang - PullRequest
0 голосов
/ 04 мая 2018

Ниже приведен весь код программы. Это сервис, который перенаправляет запросы. В данный момент работает. Я пытаюсь избавиться от файла yml, в котором в данный момент хранятся все конфиги, и переместить их в базу данных. Я не хочу много возиться с кодом, поэтому моя идея заключалась в том, чтобы просто хранить данные БД в тех же структурах.

    // Config contains configuration for this service
type Instance struct {
    User         string `json:"user"`
    Password     string `json:"password"`
    InstanceId   string `json:"instance_id"`
    InstanceType string `json:"instance_type"`
    InstanceMode string `json:"instance_mode"`
    ClientId     string `json:"client_id"`
    ClientSecret string `json:"client_secret"`
    PublicKey    string `json:"pubkey"`
    Apis         Api    `json:"apis"`
}

// API struct
type Api struct {
    Name    string `json:"name"`
    Url     string `json:"url"`
    Version string `json:"version"`
    IsBhdGw bool   `json:"isBhdGw"`
    Key     string `json:"key"`
}


// API struc
type InfoResponse struct {
    InstanceId   string `json:"instance_id"`
    InstanceType string `json:"instance_type"`
    InstanceMode string `json:"instance_mode"`
    ClientId     string `json:"client_id"`
    ClientSecret string `json:"client_secret"`
    PublicKey    string `json:"pubkey"`
    Apis         Api    `json:"apis"`
}

type Settings struct {
    Port   int    `json:"port"`
    User   string `json:"user"`
    Secret string `json:"secret"`
    Mode   string `json:"mode"`
}

type Instances struct {
    Instances []Instance
}

var payloadLength int = 3
var instances Instances
var settings Settings
var db *sql.DB



func fetchInstances() []Instance {

    rows, err := db.Query("SELECT Instances.InstanceId, Instances.User, Instances.Password, Instances.InstanceType, Instances.InstanceMode, Instances.ClientId,  Instances.ClientSecret, Instances.PublicKey, Api.Name, Api.Url, Api.Version, Api.IsBhdGw, Api.Key FROM Instances, Api")

    if err != nil {
        panic(err.Error())
    }

    defer rows.Close()

    instances := []Instance{}


    for rows.Next() {
        var instance Instance
        var apis Api

        err := rows.Scan(&instance.InstanceId, &instance.User, &instance.Password,
            &instance.InstanceType, &instance.InstanceMode, &instance.ClientId, &instance.ClientSecret, &instance.PublicKey,
            &apis.Name, &apis.Url, &apis.Version, &apis.IsBhdGw, &apis.Key)

        if err != nil {
            panic(err.Error())
        }

        instance.Apis = apis

        instances = append(instances, instance)
    }

    return instances
}

Когда я запускаю это, я получаю «паника: ошибка времени выполнения: неверный адрес памяти или разыменование нулевого указателя»

1 Ответ

0 голосов
/ 04 мая 2018

Вы пытаетесь подключиться к неинициализированному соединению с базой данных. Это связано с изменением теней.

Хотя вы определили глобальную db переменную:

var db *sql.DB

Ваш метод main() создает новый при подключении:

db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@tcp(db:3306)/"+dbName)

Итак, когда вы вызываете fetchInstances, который использует глобальную переменную, глобальная переменная все еще не установлена.

Самое простое решение - изменить код в main() следующим образом:

var err error
db, err = sql.Open(dbDriver, dbUser+":"+dbPass+"@tcp(db:3306)/"+dbName)

Но лучшее решение - никогда не использовать глобальную переменную. Используйте локально определенную переменную в main, затем передайте ее в fetchInstances.


В качестве примечания: ВСЕГДА, ВСЕГДА проверяйте свои ошибки. Дважды в вашем коде вы не можете проверить ошибки соединения с БД, как в:

db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@tcp(db:3306)/"+dbName)
err = db.Ping()

if err != nil {
    fmt.Println(err)
    os.Exit(1)
}

Если соединение не установлено, ваш db.Ping() вызов, скорее всего, вызовет панику. Вместо этого вы должны сделать:

db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@tcp(db:3306)/"+dbName)
if err != nil {
    fmt.Println(err)
    os.Exit(1)
}

err = db.Ping()

if err != nil {
    fmt.Println(err)
    os.Exit(1)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...