Я видел несколько вопросов по Go defer
, но ничего похожего на реализацию, которую я пытаюсь сделать.
Тестовый пример
Приложение Я пишу довольно много дБ транзакций, поэтому у меня есть функция
func getCursor() *sql.Tx {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
panic(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err)
}
tx, err := db.Begin()
handleErr(err, tx)
return tx
}
, которая возвращает мне транзакцию, и defer
db.Close()
, поэтому я не заполняю базу данных pool.
Другие функции, которые используют это:
// addPerson lets you add a person using a transaction that's passed as the first argument.
func addPerson(tx *sql.Tx, firstName string, lastName string, phoneNumber string) sql.Result {
statement := "INSERT INTO public.persons (first_name, last_name, phone_number, data) VALUES ($1, $2, $3, '{}')"
res, err := tx.Exec(statement, firstName, lastName, phoneNumber)
handleErr(err, tx)
return res
}
// wraps addPerson in a transaction to be used as standalong
func AddPerson(firstName string, lastName string, phoneNumber string) int64 {
tx := getCursor()
defer tx.Rollback()
err := tx.Commit()
res := addPerson(tx, firstName, lastName, phoneNumber)
handleErr(err, tx)
affected, err := res.RowsAffected()
handleErr(err, tx)
return affected
}
из https://blog.golang.org/defer-panic-and-recover
Отложенные вызовы функций выполняются в порядке «последний пришел - первый вышел» после возврата окружающей функции.
Поэтому, если tx.Commit()
завершится неудачно, транзакция будет откатана.
Моя путаница вокруг defer db.Close()
. Если это выполняется после того, как getCursor
сделано, как я все еще могу сделать INSERT
в базу данных? (Код в вопросе работает, меня просто смущает, почему он работает). Любая помощь в разъяснении очень ценится.