Как вы передаете часть * interface {} в качестве аргументов? - PullRequest
0 голосов
/ 07 декабря 2018

Я хочу использовать Scan() в пакете sql, но количество столбцов и, следовательно, количество аргументов будут меняться во время выполнения.Это подпись Scan():

func (rs *Rows) Scan(dest ...interface{}) error

Согласно документации, *interface{} является одним из типов, принятых Scan().Поэтому я хочу создать фрагмент []*interface{}, который будет расширен в качестве аргументов.

Я думал, что это сработает:

func query(database *sql.DB) {
    rows, _ := database.Query("select * from testTable")

    for rows.Next() {
        data := make([]*interface{}, 2)
        err := rows.Scan(data...) // Compilation error
        fmt.Printf("%v%v\n", *data[0], *data[1])
        if err != nil {
            fmt.Println(err.Error())
        }
    }
}

Компиляция завершится неудачно с cannot use data (type []*interface {}) as type []interface {} in argument to rows.Scan.Я думал, что data... расширится до &data[0], &data[1], но, видимо, нет.Я не понимаю сообщение об ошибке.*interface{} совместим с interface{}, так почему я не могу расширить указатель на типы интерфейсов?

Это работает:

func query(database *sql.DB) {
    rows, _ := database.Query("select * from testTable")

    for rows.Next() {
        data := make([]*interface{}, 2)
        err := rows.Scan(&data[0], &data[1]) // Only changed this line
        fmt.Printf("%v%v\n", *data[0], *data[1]) // Outputs "[48][116 101 120 116]"
        if err != nil {
            fmt.Println(err.Error())
        }
    }
}

Однако я не могу использовать этопотому что количество столбцов неизвестно во время компиляции.Как я могу написать этот код, чтобы я мог передать переменное число от *interface{} до rows.Scan()?

1 Ответ

0 голосов
/ 07 декабря 2018

Во-первых, вы не должны использовать []*interface{} часть указателей для интерфейса вместо []interface{}, где интерфейсы являются указателями.[]*interface{} отличается от []interface{}.Просто создайте часть интерфейсов, где каждый элемент является указателем на конкретный тип.

Вот фрагмент кода, как вы это сделаете.

var x int
var s string

data := []interface{}{&x, &s}

rows.Scan(data...)

Примечание по использованию ... оператор распространения.

Вот несколько связанных вопросов, которые объяснят немного больше:

golang: кусочек структуры! = кусочек интерфейса, который он реализует?

Невозможно преобразовать строку [] в интерфейс [] {}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...