Ваш вопрос не так прост, как может показаться на первый взгляд.
1. Давайте проясним проблему
Вопрос не о конкретной базе данных, такой как pgsql / mysql / sqlite / other, а о любом общем диске базы данных.
Таким образом, ответ должен быть в database/sql/driver
. Пойдем дальше.
2. sql/driver
. Интерфейсы: Queryer
/ QueryerContext
& Execer
/ ExecerContext
Модуль sql/driver
определяет интерфейсы:
Queryer
/ QeueryerContext
- для возможности(*DB).Query
Execer
/ ExecerContext
- для (*DB).Exec
- других, таких как
Pinger
Обратите внимание, что каждый интерфейс описан в документации как "дополнительный интерфейс, который может быть реализован с помощью Conn"
Это означает, что можно реализовать драйвер sql без Query
и / или Exec
.
3. Экспериментальная проверка
Давайте попробуем реализовать правильный драйвер базы данных, который не может Query
и Exec
: https://play.golang.org/p/sZiigEghphE
package main
import (
"database/sql"
"database/sql/driver"
"log"
)
type expdrv struct{}
type expconn struct{}
// sql.Driver implementation
func (*expdrv) Open(name string) (driver.Conn, error) {
return &expconn{}, nil
}
// driver.Conn implementation
func (c *expconn) Prepare(query string) (driver.Stmt, error) {
return nil, nil
}
func (c *expconn) Close() error {
return nil
}
func (c *expconn) Begin() (driver.Tx, error) {
return nil, nil
}
func main() {
sql.Register("drvexp", &expdrv{})
log.Printf("Registred drivers: %v\n", sql.Drivers())
db, err := sql.Open("drvexp", "")
log.Printf("sql.Open() success: %v, error: %v", db != nil, err)
log.Println("db.Close() error:", db.Close())
}
2009/11/10 23:00:00 Registred drivers: [drvexp]
2009/11/10 23:00:00 sql.Open() success: true, error:
2009/11/10 23:00:00 db.Ping() success: true
2009/11/10 23:00:00 db.Close() success: true
2009/11/10 23:00:00 db.Ping() result: sql: database is closed
Это работает! Эта реализация Driver
:
- правильно с
database/sql
точки зрения - не имеет методов работы
Query
и Exec
(попытка вызовет панику) - удивительно работающий
Ping()
4. Возможность реализации Exec
или Query
независимо друг от друга
Давайте добавим Exec
:
// driver.Result & driver.Execer
type expresult struct{}
func (*expconn) Exec(query string, args []driver.Value) (driver.Result, error) {
return &expresult{}, nil
}
func (*expresult) LastInsertId() (int64, error) {
return 0, nil
}
func (*expresult) RowsAffected() (int64, error) {
return 0, nil
}
позволит:
_, err = db.Exec("BYE")
fmt.Println("db.Exec() success:", err == nil) // Outputs: true
5. Заключение
Возможность вызова Query/QueryContext
и / или Exec/ExecContext
является необязательной
Поведение этих методов может сильно различаться у разных драйверов
В общем случае правильного ответа не существует
Для особых случаев (с определенным драйвером):
- можно предположить , что
db.Query
будет работать в большинстве случаев - , но невозможно гарантировать , что
Query
действительно будет работатьбез экспериментальной проверки
Спасибо за внимание!
Полагаю, это окончательный ответ.