sqlx æ¯ Go è¯Âè¨Âä¸Âä¸Â个æµÂè¡ÂçÂÂ第ä¸Âæ¹åÂÂ
ï¼Âå®ÂæÂÂä¾ÂäºÂ对 Go æ ÂÃ¥ÂÂ庠database/sql
çÂÂæ©å±Âï¼Âæ¨å¨ç®ÂÃ¥ÂÂÃ¥ÂÂæ¹迠Go è¯Âè¨Âä¸Â使ç¨ SQL çÂÂä½ÂéªÂï¼Â并æÂÂä¾ÂäºÂæ´å 强大çÂÂæ°æ®åºÂ交äºÂÃ¥ÂÂè½ãÂÂsqlx
ä¿ÂçÂÂ亠database/sql
æÂ¥å£ä¸ÂÃ¥ÂÂï¼Âæ¯ database/sql
çÂÂè¶Â
éÂÂï¼Âè¿Â使å¾Âå°Âç°æÂÂ项ç®ä¸Â使ç¨ç database/sql
æ¿æ¢为 sqlx
Ã¥ÂÂå¾Âç¸å½Âè½»æ¾ãÂÂ
æ¾ÂÂéÂÂç¹讲解 sqlx
å¨ database/sql
åºç¡Âä¸Âæ©å±ÂçÂÂÃ¥ÂÂè½ï¼Â对亠database/sql
å·²ç»Âæ¯æÂÂçÂÂÃ¥ÂÂè½åÂÂä¸Âä¼Â详ç»Â讲解ãÂÂå¦ÂæÂÂ你对 database/sql
ä¸ÂçÂÂæÂÂï¼Âå¯以æÂ¥çÂÂæÂÂçÂÂå¦ä¸Âç¯ÂæÂÂç« ãÂÂå¨ Go ä¸Âå¦Âä½Â使ç¨ database/sql æÂ¥æÂÂä½Âæ°æ®åºÂãÂÂãÂÂ
å®Âè£Â
sqlx
å®Âè£Â
æ¹å¼Âå Go è¯Âè¨Âä¸ÂÃ¥Â
¶ä»Â第ä¸Âæ¹åÂÂ
ä¸Âæ ·ï¼Â
$ go get github.com/jmoiron/sqlx
sqlx ç±»åÂÂ设计
sqlx
çÂÂ设计丠database/sql
å·®å«ä¸Â大ï¼Âç¼Âç Âé£Âæ ¼è¾Â为ç»Âä¸Âï¼ÂÃ¥ÂÂè database/sql
æ ÂÃ¥ÂÂåºÂï¼Âsqlx
æÂÂä¾ÂäºÂå¦Âä¸Âå ç§Âä¸Âä¹Â对åºÂçÂÂæ°æ®类åÂÂï¼Â
sqlx.DB
ï¼Â类似äºÂsql.DB
ï¼Â表示æ°æ®åºÂ对象ï¼Âå¯以ç¨æÂ¥æÂÂä½Âæ°æ®åºÂãÂÂsqlx.Tx
ï¼Â类似äºÂsql.Tx
ï¼ÂäºÂå¡对象ãÂÂsqlx.Stmt
ï¼Â类似äºÂsql.Stmt
ï¼Âé¢Âå¤Âç SQL è¯Âå¥ãÂÂsqlx.NamedStmt
ï¼Â对sqlx.Stmt
çÂÂå°Â裠ï¼Âæ¯æÂÂå ·åÂÂÃ¥ÂÂæ°ãÂÂsqlx.Rows
ï¼Â类似äºÂsql.Rows
ï¼Âsqlx.Queryx
çÂÂè¿ÂÃ¥ÂÂç»ÂæÂÂãÂÂsqlx.Row
ï¼Â类似äºÂsql.Row
ï¼Âsqlx.QueryRowx
çÂÂè¿ÂÃ¥ÂÂç»ÂæÂÂãÂÂ
以ä¸Âç±»åÂÂ丠database/sql
æÂÂä¾ÂçÂÂ对åºÂç±»åÂÂå¨åÂÂè½ä¸Âåºå«ä¸Â大ï¼Âä½ sqlx
为è¿ÂäºÂç±»åÂÂæÂÂä¾ÂäºÂæ´åÂÂ好çÂÂæ¹æ³ÂãÂÂ
Ã¥ÂÂå¤Â
为äºÂæ¼Â示 sqlx
ç¨æ³Âï¼ÂæÂÂÃ¥ÂÂå¤ÂäºÂå¦Â丠MySQL æ°æ®åºÂ表ï¼Â
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL COMMENT 'ç¨æ·åÂÂ',
`email` varchar(255) NOT NULL DEFAULT '' COMMENT 'é®箱',
`age` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'å¹´é¾Â',
`birthday` datetime DEFAULT NULL COMMENT 'çÂÂæÂÂ¥',
`salary` varchar(128) DEFAULT NULL COMMENT 'èª水',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `u_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='ç¨æ·表';
ä½ å¯以使ç¨ MySQL å½令è¡ÂæÂÂå¾形åÂÂ工堷åÂÂ建è¿Â张表ãÂÂ
è¿ÂæÂ¥æ°æ®åºÂ
使ç¨ sqlx
è¿ÂæÂ¥æ°æ®åºÂï¼Â
package main
import (
"database/sql"
"log"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
func main() {
var (
db *sqlx.DB
err error
dsn = "user:password@tcp(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=true&loc=Local"
)
// 1. 使ç¨ sqlx.Open è¿ÂæÂ¥æ°æ®åºÂ
db, err = sqlx.Open("mysql", dsn)
if err != nil {
log.Fatal(err)
}
// 2. 使ç¨ sqlx.Open Ã¥ÂÂä½Âæ¹泠sqlx.MustOpen è¿ÂæÂ¥æ°æ®åºÂï¼Âå¦ÂæÂÂåºç°éÂÂ误ç´æÂÂ¥ panic
db = sqlx.MustOpen("mysql", dsn)
// 3. å¦ÂæÂÂå·²ç»ÂæÂÂ亠*sql.DB 对象ï¼ÂÃ¥ÂÂå¯以使ç¨ sqlx.NewDb è¿ÂæÂ¥æ°æ®åºÂï¼Âå¾Âå° *sqlx.DB 对象
sqlDB, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatal(err)
}
db = sqlx.NewDb(sqlDB, "mysql")
// 4. 使ç¨ sqlx.Connect è¿ÂæÂ¥æ°æ®åºÂï¼ÂçÂÂ价亠sqlx.Open + db.Ping
db, err = sqlx.Connect("mysql", dsn)
if err != nil {
log.Fatal(err)
}
// 5. 使ç¨ sqlx.Connect Ã¥ÂÂä½Âæ¹泠sqlx.MustConnect è¿ÂæÂ¥æ°æ®åºÂï¼Âå¦ÂæÂÂåºç°éÂÂ误ç´æÂÂ¥ panic
db = sqlx.MustConnect("mysql", dsn)
}
å¨ sqlx
ä¸ÂæÂÂ们å¯以éÂÂè¿Â以丠5 ç§Âæ¹å¼Âè¿ÂæÂ¥æ°æ®åºÂãÂÂ
sqlx.Open
对栠sql.Open
æ¹æ³Âï¼Âè¿Âå *sqlx.DB
ç±»åÂÂãÂÂ
sqlx.MustOpen
丠sqlx.Open
ä¸Âæ ·ä¼Âè¿Âå *sqlx.DB
å®Âä¾Âï¼Âä½Âå¦ÂæÂÂéÂÂå°éÂÂ误åÂÂä¼ panic
ãÂÂ
sqlx.NewDb
æ¯æÂÂä»Âä¸Â个 database/sql
Ã¥ÂÂ
ç *sql.DB
对象åÂÂ建ä¸Â个æ°ç *sqlx.DB
ç±»åÂÂï¼Â并ä¸ÂéÂÂè¦ÂæÂÂå®Â驱å¨åÂÂ称ãÂÂ
使ç¨å 3 ç§Âæ¹å¼Âè¿ÂæÂ¥æ°æ®åºÂ并ä¸Âä¼Âç«Âå³ä¸Âæ°æ®åºÂ建ç«Âè¿ÂæÂ¥ï¼Âè¿ÂæÂ¥å°Âä¼Âå¨åÂÂéÂÂçÂÂæ¶åÂÂ延è¿Â建ç«ÂãÂÂ为äºÂç¡®ä¿Âè½å¤Âæ£常è¿ÂæÂ¥æ°æ®åºÂï¼Âå¾Âå¾ÂéÂÂè¦Âè°Âç¨ db.Ping()
æ¹æ³Âè¿Âè¡ÂéªÂè¯Âï¼Â
ctx := context.Background()
if err := db.PingContext(ctx); err != nil {
log.Fatal(err)
}
sqlx
æÂÂä¾Âç sqlx.Connect
æ¹æ³Âå°±æ¯ç¨æÂ¥ç®ÂÃ¥ÂÂè¿Âä¸ÂæÂÂä½ÂçÂÂï¼Âå®ÂçÂÂ价亠sqlx.Open
+ db.Ping
两个æ¹æ³Âï¼ÂÃ¥Â
¶å®Âä¹Âå¦Âä¸Âï¼Â
func Connect(driverName, dataSourceName string) (*DB, error) {
db, err := Open(driverName, dataSourceName)
if err != nil {
return nil, err
}
err = db.Ping()
if err != nil {
db.Close()
return nil, err
}
return db, nil
}
sqlx.MustConnect
æ¹æ³Âå¨ sqlx.Connect
æ¹æ³ÂçÂÂåºç¡Âä¸Âï¼ÂæÂÂä¾ÂäºÂéÂÂå°éÂÂ误ç«Âå³ panic
çÂÂÃ¥ÂÂè½ãÂÂçÂÂå° sqlx.MustConnect
æ¹æ³ÂçÂÂå®Âä¹Âä½ å°±æÂÂç½äºÂï¼Â
func MustConnect(driverName, dataSourceName string) *DB {
db, err := Connect(driverName, dataSourceName)
if err != nil {
panic(err)
}
return db
}
以åÂÂå½Âä½ éÂÂ觠MustXxx
类似æ¹æ³ÂÃ¥ÂÂæ¶就åºÂ该æ³å°ï¼ÂÃ¥Â
¶åÂÂè½å¾Âå¾ÂçÂÂ价亠Xxx
æ¹æ³Âï¼Âä¸Âè¿Âå¨åÂ
¶åÂÂ
é¨å®Âç°ä¸Âï¼ÂéÂÂå° error
ä¸ÂÃ¥ÂÂè¿ÂÃ¥ÂÂï¼ÂèÂÂæ¯ç´æÂ¥è¿Âè¡ panic
ï¼Âè¿Âä¹Âæ¯ Go è¯Âè¨Âå¾Âå¤ÂåºÂä¸ÂçÂÂæ¯ç¨æ¹æ³ÂãÂÂ
声æÂÂ模åÂÂ
æÂÂ们å®Âä¹Âä¸Â个 User
ç»ÂæÂÂä½ÂæÂ¥æ å°Âæ°æ®åºÂä¸Âç user
表ï¼Â
type User struct {
ID int
Name sql.NullString `json:"username"`
Email string
Age int
Birthday time.Time
Salary Salary
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
type Salary struct {
Month int `json:"month"`
Year int `json:"year"`
}
// Scan implements sql.Scanner, use custom types in *sql.Rows.Scan
func (s *Salary) Scan(src any) error {
if src == nil {
return nil
}
var buf []byte
switch v := src.(type) {
case []byte:
buf = v
case string:
buf = []byte(v)
default:
return fmt.Errorf("invalid type: %T", src)
}
err := json.Unmarshal(buf, s)
return err
}
// Value implements driver.Valuer, use custom types in Query/QueryRow/Exec
func (s Salary) Value() (driver.Value, error) {
v, err := json.Marshal(s)
return string(v), err
}
User
ç»ÂæÂÂä½Âå¨è¿ÂéÂÂå¯以被称为ãÂÂ模åÂÂãÂÂãÂÂ
æ§衠SQL å½令
database/sql
Ã¥ÂÂ
æÂÂä¾Â亠*sql.DB.Exec
æ¹æ³ÂæÂ¥æ§è¡Âä¸Âæ¡ SQL å½令ï¼Âsqlx
对åÂ
¶è¿Âè¡ÂäºÂæ©å±Âï¼ÂæÂÂä¾Â亠*sqlx.DB.MustExec
æ¹æ³ÂæÂ¥æ§è¡Âä¸Âæ¡ SQL å½令ï¼Â
func MustCreateUser(db *sqlx.DB) (int64, error) {
birthday := time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local)
user := User{
Name: sql.NullString{String: "jianghushinian", Valid: true},
Email: "jianghushinian007@outlook.com",
Age: 10,
Birthday: birthday,
Salary: Salary{
Month: 100000,
Year: 10000000,
},
}
res := db.MustExec(
`INSERT INTO user(name, email, age, birthday, salary) VALUES(?, ?, ?, ?, ?)`,
user.Name, user.Email, user.Age, user.Birthday, user.Salary,
)
return res.LastInsertId()
}
è¿ÂéÂÂ使ç¨ *sqlx.DB.MustExec
æ¹æ³ÂæÂÂÃ¥Â
¥äºÂä¸Âæ¡ user
è®°å½ÂãÂÂ
*sqlx.DB.MustExec
æ¹æ³Âå®Âä¹Âå¦Âä¸Âï¼Â
func (db *DB) MustExec(query string, args ...interface{}) sql.Result {
return MustExec(db, query, args...)
}
func MustExec(e Execer, query string, args ...interface{}) sql.Result {
res, err := e.Exec(query, args...)
if err != nil {
panic(err)
}
return res
}
ä¸ÂÃ¥ÂÂæÂÂä»Âç»Âç sqlx.MustOpen
æ¹æ³Âä¸Âæ ·ï¼Â*sqlx.DB.MustExec
æ¹æ³Âä¹Âä¼Âå¨éÂÂå°éÂÂ误æ¶ç´æÂÂ¥ panic
ï¼ÂÃ¥Â
¶åÂÂ
é¨è°Âç¨çÂÂæ¯ *sqlx.DB.Exec
æ¹æ³ÂãÂÂ
æ§衠SQL æ¥询
database/sql
Ã¥ÂÂ
æÂÂä¾Â亠*sql.DB.Query
å *sql.DB.QueryRow
两个æ¥询æ¹æ³Âï¼ÂÃ¥Â
¶ç¾åÂÂå¦Âä¸Âï¼Â
func (db *DB) Query(query string, args ...any) (*Rows, error)
func (db *DB) QueryRow(query string, args ...any) *Row
sqlx
å¨è¿Â两个æ¹æ³ÂçÂÂåºç¡Âä¸Âï¼Âæ©å±Âåºå¦Âä¸Â两个æ¹æ³Âï¼Â
func (db *DB) Queryx(query string, args ...interface{}) (*Rows, error)
func (db *DB) QueryRowx(query string, args ...interface{}) *Row
è¿Â两个æ¹æ³Âè¿ÂÃ¥ÂÂçÂÂç±»åÂÂæ£æ¯åÂÂæ sqlx ç±»åÂÂ设计 ä¸ÂæÂÂå°ç sqlx.Rows
ãÂÂsqlx.Row
ç±»åÂÂãÂÂ
ä¸Âé¢æ¥讲解ä¸Âè¿Â两个æ¹æ³Âå¦Âä½Â使ç¨ãÂÂ
Queryx
使ç¨ *sqlx.DB.Queryx
æ¹æ³Âæ¥询记å½Âå¦Âä¸Âï¼Â
func QueryxUsers(db *sqlx.DB) ([]User, error) {
var us []User
rows, err := db.Queryx("SELECT * FROM user")
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var u User
// sqlx æÂÂä¾ÂäºÂ便æ·æ¹æ³Âå¯以å°Âæ¥询ç»ÂæÂÂç´æÂ¥æ«æÂÂå°ç»ÂæÂÂä½Â
err = rows.StructScan(&u)
if err != nil {
return nil, err
}
us = append(us, u)
}
return us, nil
}
*sqlx.DB.Queryx
æ¹æ³Âç¾åÂÂè½ç¶丠*sql.DB.Query
æ¹æ³Âåºæ¸åÂÂï¼Âä½Âå®Âè¿ÂÃ¥ÂÂç±»å *sqlx.Rows
å¾Âå°äºÂæ©å±Âï¼ÂÃ¥Â
¶æÂÂä¾Âç StructScan
æ¹æ³Âè½å¤Âæ¹便çÂÂå°Âæ¥询ç»ÂæÂÂç´æÂ¥æ«æÂÂå° User
ç»ÂæÂÂä½Âï¼Âè¿ÂæÂÂ大çÂÂå¢Âå äºÂ便æºæ§ï¼ÂæÂÂ们åÂÂä¹Âä¸Âç¨åÂÂ使ç¨ *sql.Rows
æÂÂä¾Âç Scan
æ¹æ³Âé£样æ¨个åÂÂåº User
çÂÂå±Âæ§äºÂãÂÂ
QueryRowx
使ç¨ *sqlx.DB.QueryRowx
æ¹æ³Âæ¥询记å½Âå¦Âä¸Âï¼Â
func QueryRowxUser(db *sqlx.DB, id int) (User, error) {
var u User
err := db.QueryRowx("SELECT * FROM user WHERE id = ?", id).StructScan(&u)
return u, err
}
*sqlx.Row
Ã¥ÂÂæ ·æÂÂä¾Â亠StructScan
æ¹æ³Âå°Âæ¥询ç»ÂæÂÂæ«æÂÂå°ç»ÂæÂÂä½ÂãÂÂ
å¦å¤Âï¼Âè¿ÂéÂÂ使ç¨äºÂé¾å¼Âè°Âç¨çÂÂæ¹å¼Âï¼Âå¨è°Âç¨ db.QueryRowx()
ä¹ÂÃ¥ÂÂç´æÂ¥è°Âç¨亠.StructScan(&u)
ï¼ÂæÂ¥æ¶ç err
æ¯ StructScan
çÂÂè¿ÂÃ¥ÂÂç»ÂæÂÂãÂÂè¿Âæ¯å 为 db.QueryRowx()
çÂÂè¿ÂÃ¥ÂÂç»Âæ *sqlx.Row
ä¸Âè®°å½ÂäºÂéÂÂ误信æ¯ err
ï¼Âå¦ÂæÂÂæ¥询é¶段éÂÂå°éÂÂ误ä¼Â被记å½Âå° *sqlx.Row.err
ä¸ÂãÂÂå¨è°Âç¨ StructScan
æ¹æ³Âé¶段ï¼ÂÃ¥Â
¶åÂÂ
é¨é¦ÂÃ¥Â
Âå¤æ r.err != nil
ï¼Âå¦ÂæÂÂÃ¥ÂÂå¨ err
ç´æÂ¥è¿ÂÃ¥ÂÂéÂÂ误ï¼Â没æÂÂéÂÂ误åÂÂå°Âæ¥询ç»ÂæÂÂæ«æÂÂå° dest
Ã¥ÂÂæ°æÂ¥æ¶å°çÂÂç»ÂæÂÂä½ÂæÂÂéÂÂï¼Â代ç Âå®Âç°å¦Âä¸Âï¼Â
type Row struct {
err error
unsafe bool
rows *sql.Rows
Mapper *reflectx.Mapper
}
func (r *Row) StructScan(dest interface{}) error {
return r.scanAny(dest, true)
}
func (r *Row) scanAny(dest interface{}, structOnly bool) error {
if r.err != nil {
return r.err
}
...
}
sqlx
ä¸Âä»Â
æ©å±Â亠*sql.DB.Query
å *sql.DB.QueryRow
两个æ¥询æ¹æ³Âï¼Âå®Âè¿Âæ°å¢ÂäºÂ两个æ¥询æ¹æ³Âï¼Â
func (db *DB) Get(dest interface{}, query string, args ...interface{}) error
func (db *DB) Select(dest interface{}, query string, args ...interface{}) error
*sqlx.DB.Get
æ¹æ³ÂÃ¥ÂÂ
è£Â
亠*sqlx.DB.QueryRowx
æ¹æ³Âï¼Âç¨以ç®ÂÃ¥ÂÂæ¥询åÂÂæ¡记å½ÂãÂÂ
*sqlx.DB.Select
æ¹æ³ÂÃ¥ÂÂ
è£Â
亠*sqlx.DB.Queryx
æ¹æ³Âï¼Âç¨以ç®ÂÃ¥ÂÂæ¥询å¤Âæ¡记å½ÂãÂÂ
æÂ¥ä¸Âæ¥讲解è¿Â两个æ¹æ³Âå¦Âä½Â使ç¨ãÂÂ
Get
使ç¨ *sqlx.DB.Get
æ¹æ³Âæ¥询记å½Âå¦Âä¸Âï¼Â
func GetUser(db *sqlx.DB, id int) (User, error) {
var u User
// æ¥询记å½Âæ«æÂÂæ°æ®å° struct
err := db.Get(&u, "SELECT * FROM user WHERE id = ?", id)
return u, err
}
å¯以åÂÂç° *sqlx.DB.Get
æ¹æ³Âç¨起æÂ¥éÂÂ常ç®ÂÃ¥ÂÂï¼ÂæÂÂ们ä¸ÂÃ¥ÂÂéÂÂè¦Âè°Âç¨ StructScan
æ¹æ³Âå°Âæ¥询ç»ÂæÂÂæ«æÂÂå°ç»ÂæÂÂä½Âä¸Âï¼ÂåªéÂÂè¦Âå°Âç»ÂæÂÂä½ÂæÂÂéÂÂå½Âä½ Get
æ¹æ³ÂçÂÂ第ä¸Â个åÂÂæ°传éÂÂè¿ÂÃ¥ÂȌ³å¯ãÂÂ
堶代ç Âå®Âç°å¦Âä¸Âï¼Â
func (db *DB) Get(dest interface{}, query string, args ...interface{}) error {
return Get(db, dest, query, args...)
}
func Get(q Queryer, dest interface{}, query string, args ...interface{}) error {
r := q.QueryRowx(query, args...)
return r.scanAny(dest, false)
}
æ ¹æ®æºÂç Âå¯以çÂÂåºï¼Â*sqlx.DB.Get
Ã¥ÂÂ
é¨è°Âç¨亠*sqlx.DB.QueryRowx
æ¹æ³ÂãÂÂ
Select
使ç¨ *sqlx.DB.Select
æ¹æ³Âæ¥询记å½Âå¦Âä¸Âï¼Â
func SelectUsers(db *sqlx.DB) ([]User, error) {
var us []User
// æ¥询记å½Âæ«æÂÂæ°æ®å° slice
err := db.Select(&us, "SELECT * FROM user")
return us, err
}
å¯以åÂÂç° *sqlx.DB.Select
æ¹æ³Âç¨起æÂ¥åÂÂæ ·éÂÂ常ç®ÂÃ¥ÂÂï¼Âå®Âå¯以ç´æÂ¥å°Âæ¥询ç»ÂæÂÂæ«æÂÂå° []User
Ã¥ÂÂçÂÂä¸ÂãÂÂ
堶代ç Âå®Âç°å¦Âä¸Âï¼Â
func (db *DB) Select(dest interface{}, query string, args ...interface{}) error {
return Select(db, dest, query, args...)
}
func Select(q Queryer, dest interface{}, query string, args ...interface{}) error {
rows, err := q.Queryx(query, args...)
if err != nil {
return err
}
// if something happens here, we want to make sure the rows are Closed
defer rows.Close()
return scanAll(rows, dest, false)
}
æ ¹æ®æºÂç Âå¯以çÂÂåºï¼Â*sqlx.DB.Select
Ã¥ÂÂ
é¨è°Âç¨亠*sqlx.DB.Queryx
æ¹æ³ÂãÂÂ
sqlx.In
å¨ database/sql
ä¸Âå¦ÂæÂÂæ³è¦Âæ§衠SQL IN æ¥询ï¼Âç±亠IN æ¥询åÂÂæ°é¿度ä¸Âåºå®Âï¼ÂæÂÂ们ä¸Âå¾Âä¸Â使ç¨ fmt.Sprintf
æÂ¥å¨æÂÂæ¼æÂÂ¥ SQL è¯Âå¥ï¼Â以ä¿Â诠SQL ä¸ÂÃ¥ÂÂæ°å ä½Â符çÂÂ个æ°æ¯æ£确çÂÂãÂÂ
sqlx
æÂÂä¾Â亠In
æ¹æ³ÂæÂ¥æ¯æ SQL IN æ¥询ï¼Âè¿ÂæÂÂ大çÂÂç®ÂÃ¥ÂÂäºÂ代ç Âï¼Âä¹Â使å¾Â代ç Âæ´æÂÂç»´æ¤åÂÂå®ÂÃ¥Â
¨ãÂÂ
使ç¨示ä¾Âå¦Âä¸Âï¼Â
func SqlxIn(db *sqlx.DB, ids []int64) ([]User, error) {
query, args, err := sqlx.In("SELECT * FROM user WHERE id IN (?)", ids)
if err != nil {
return nil, err
}
query = db.Rebind(query)
rows, err := db.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var us []User
for rows.Next() {
var user User
err = rows.Scan(&user.ID, &user.Name, &user.Email, &user.Age,
&user.Birthday, &user.Salary, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
return nil, err
}
us = append(us, user)
}
return us, nil
}
è°Âç¨ sqlx.In
并传é SQL è¯Âå¥以åÂÂÃ¥ÂÂçÂÂç±»åÂÂçÂÂÃ¥ÂÂæ°ï¼Âå®Âå°Âè¿ÂÃ¥ÂÂæ°çÂÂæ¥询 SQL query
以åÂÂÃ¥ÂÂæ° args
ï¼Âè¿Â个 query
å°Âä¼Âæ ¹æ® ids
æÂ¥å¨æÂÂè°Âæ´ãÂÂ
æ¯Âå¦ÂæÂÂ们传é ids
为 []int64{1, 2, 3}
ï¼ÂÃ¥ÂÂå¾Âå° query
为 SELECT * FROM user WHERE id IN (?, ?, ?)
ãÂÂ
注æÂÂï¼ÂæÂÂ们æÂ¥ä¸ÂæÂ¥åÂÂè°Âç¨ db.Rebind(query)
éÂÂæ°ç»Âå®Â亠query
Ã¥ÂÂéÂÂçÂÂÃ¥ÂÂæ°å ä½Â符ãÂÂå¦ÂæÂÂ你使ç¨ MySQL æ°æ®åºÂï¼Âè¿Âä¸Âæ¯å¿Â
é¡»çÂÂï¼Âå 为æÂÂ们使ç¨ç MySQL 驱å¨ç¨ÂåºÂÃ¥ÂÂæ°å ä½Â符就æ¯ ?
ãÂÂèÂÂå¦ÂæÂÂ你使ç¨ PostgreSQL æ°æ®åºÂï¼Âç±亠PostgreSQL 驱å¨ç¨ÂåºÂÃ¥ÂÂæ°å ä½Â符æ¯ $n
ï¼Âè¿Âæ¶就å¿Â
é¡»è¦Âè°Âç¨ db.Rebind(query)
æ¹æ³Âæ¥转æ¢åÂÂæ°å ä½Â符äºÂãÂÂ
å®Âä¼Âå° SELECT * FROM user WHERE id IN (?, ?, ?)
ä¸ÂçÂÂÃ¥ÂÂæ°å ä½Â符转æ¢为 PostgreSQL 驱å¨ç¨ÂåºÂè½å¤Âè¯Âå«çÂÂÃ¥ÂÂæ°å ä½Â符 SELECT * FROM user WHERE id IN ($1, $2, $3)
ãÂÂ
ä¹ÂÃ¥ÂÂçÂÂ代ç Âå°±è·Â使ç¨ database/sql
æ¥询记å½Â没ä»Âä¹Â两样äºÂãÂÂ
使ç¨堷åÂÂÃ¥ÂÂæ°
sqlx
æÂÂä¾ÂäºÂ两个æ¹泠NamedExec
ãÂÂNamedQuery
ï¼Âå®Â们è½å¤Âæ¯æÂÂÃ¥Â
·åÂÂÃ¥ÂÂæ° :name
ï¼Âè¿Âæ ·å°±ä¸Âå¿Â
Ã¥ÂÂ使ç¨ ?
è¿Âç§Âå ä½Â符çÂÂå½¢å¼ÂäºÂãÂÂ
è¿Â两个æ¹æ³Âç¾åÂÂå¦Âä¸Âï¼Â
func (db *DB) NamedExec(query string, arg interface{}) (sql.Result, error)
func (db *DB) NamedQuery(query string, arg interface{}) (*Rows, error)
堶使ç¨示ä¾Âå¦Âä¸Âï¼Â
func NamedExec(db *sqlx.DB) error {
m := map[string]interface{}{
"email": "jianghushinian007@outlook.com",
"age": 18,
}
result, err := db.NamedExec(`UPDATE user SET age = :age WHERE email = :email`, m)
if err != nil {
return err
}
fmt.Println(result.RowsAffected())
return nil
}
func NamedQuery(db *sqlx.DB) ([]User, error) {
u := User{
Email: "jianghushinian007@outlook.com",
Age: 18,
}
rows, err := db.NamedQuery("SELECT * FROM user WHERE email = :email OR age = :age", u)
if err != nil {
return nil, err
}
defer rows.Close()
var users []User
for rows.Next() {
var user User
err := rows.StructScan(&user)
if err != nil {
return nil, err
}
users = append(users, user)
}
return users, nil
}
æÂÂ们å¯以使ç¨ :name
çÂÂæ¹å¼ÂæÂ¥å½åÂÂÃ¥ÂÂæ°ï¼Âå®Âè½å¤Âå¹éÂ
 map
æ struct
对åºÂÃ¥ÂÂ段çÂÂÃ¥ÂÂæ°å¼ï¼Âè¿Âæ ·ç SQL è¯Âå¥å¯读æ§æ´强ãÂÂ
äºÂå¡
å¨äºÂå¡çÂÂæ¯æÂÂä¸Âï¼Âsqlx
æ©å±Âåº亠Must
çÂÂæÂÂäºÂå¡ï¼Â使ç¨示ä¾Âå¦Âä¸Âï¼Â
func MustTransaction(db *sqlx.DB) error {
tx := db.MustBegin()
tx.MustExec("UPDATE user SET age = 25 WHERE id = ?", 1)
return tx.Commit()
}
ä¸Âè¿Âè¿Âç§Âç¨æ³Âä¸Âå¤Âï¼Âä½ çÂ¥éÂÂå°±è¡ÂãÂÂ以ä¸Âæ¯äºÂå¡çÂÂæ¨èÂÂç¨æ³Âï¼Â
func Transaction(db *sqlx.DB, id int64, name string) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
res, err := tx.Exec("UPDATE user SET name = ? WHERE id = ?", name, id)
if err != nil {
return err
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return err
}
fmt.Printf("rowsAffected: %d\n", rowsAffected)
return tx.Commit()
}
æÂÂ们使ç¨ defer
è¯Âå¥æÂ¥å¤ÂçÂÂäºÂå¡çÂÂÃ¥ÂÂæ»ÂæÂÂä½Âï¼Âè¿Âæ ·å°±ä¸Âå¿Â
å¨æ¯Â次å¤ÂçÂÂéÂÂ误æ¶éÂÂå¤ÂçÂÂç¼ÂÃ¥ÂÂè°Âç¨ tx.Rollback()
çÂÂ代ç ÂãÂÂ
å¦ÂæÂÂ代ç Âæ£常æ§è¡Âå°æÂÂÃ¥ÂÂï¼ÂéÂÂè¿ tx.Commit()
æÂ¥æÂÂ交äºÂå¡ï¼Âæ¤æ¶å³使åÂÂè°Âç¨ tx.Rollback()
ä¹Âä¸Âä¼Â对ç»ÂæÂÂ产çÂÂå½±åÂÂãÂÂ
é¢Âå¤ÂçÂÂè¯ÂÃ¥ÂÂ¥
sqlx
éÂÂ对 *sql.DB.Prepare
æ©å±Âåº亠*sqlx.DB.Preparex
æ¹æ³Âï¼Âè¿Âå *sqlx.Stmt
ç±»åÂÂãÂÂ
*sqlx.Stmt
ç±»åÂÂæ¯æ Queryx
ãÂÂQueryRowx
ãÂÂGet
ãÂÂSelect
è¿Â亠sqlx
ç¹æÂÂçÂÂæ¹æ³ÂãÂÂ
堶使ç¨示ä¾Âå¦Âä¸Âï¼Â
func PreparexGetUser(db *sqlx.DB) (User, error) {
stmt, err := db.Preparex(`SELECT * FROM user WHERE id = ?`)
if err != nil {
return User{}, err
}
var u User
err = stmt.Get(&u, 1)
return u, err
}
*sqlx.DB.Preparex
æ¹æ³Âå®Âä¹Âå¦Âä¸Âï¼Â
func Preparex(p Preparer, query string) (*Stmt, error) {
s, err := p.Prepare(query)
if err != nil {
return nil, err
}
return &Stmt{Stmt: s, unsafe: isUnsafe(p), Mapper: mapperFor(p)}, err
}
å®ÂéÂÂ
丠*sqlx.DB.Preparex
Ã¥ÂÂ
é¨è¿Âæ¯è°Âç¨ç *sql.DB.Preapre
æ¹æ³Âï¼Âåªä¸Âè¿Âå°ÂÃ¥Â
¶è¿ÂÃ¥ÂÂç»ÂæÂÂæÂÂé æ *sqlx.Stmt
ç±»åÂÂ并è¿ÂÃ¥ÂÂãÂÂ
ä¸Âå®Âå ¨çÂÂæ«æÂÂ
å¨使ç¨ *sqlx.DB.Get
çÂÂæ¹æ³Âæ¥询记å½Âæ¶ï¼Âå¦Âæ SQL è¯Âå¥æ¥询åºæÂ¥çÂÂÃ¥ÂÂ段ä¸Âè¦Âç»Âå®ÂçÂÂ模åÂÂå±Âæ§ä¸Âå¹éÂ
Âï¼ÂÃ¥ÂÂä¼ÂæÂ¥éÂÂãÂÂ
示ä¾Âå¦Âä¸Âï¼Â
func GetUser(db *sqlx.DB) (User, error) {
var user struct {
ID int
Name string
Email string
// 没æ Age å±Âæ§
}
err := db.Get(&user, "SELECT id, name, email, age FROM user WHERE id = ?", 1)
if err != nil {
return User{}, err
}
return User{
ID: user.ID,
Name: sql.NullString{String: user.Name},
Email: user.Email,
}, nil
}
以ä¸Â示ä¾Â代ç Âä¸Âï¼ÂSQL è¯Âå¥ä¸Âæ¥询亠id
ãÂÂname
ãÂÂemail
ãÂÂage
4 个åÂÂ段ï¼Âè user
ç»ÂæÂÂä½ÂÃ¥ÂÂåªæ ID
ãÂÂName
ãÂÂEmail
3 个å±Âæ§ï¼Âç±äºÂæ æ³Âä¸Âä¸Â对åºÂï¼Âæ§è¡Â以ä¸Â代ç Âï¼ÂæÂÂ们å°Âå¾Âå°å¦Âä¸ÂæÂ¥éÂÂä¿¡æ¯ï¼Â
missing destination name age in *struct { ID int; Name string; Email string }
è¿Âç§Â表ç°æ¯åÂÂçÂÂçÂÂï¼Â符å Go è¯Âè¨ÂçÂÂç¼Âç¨Âé£Âæ ¼ï¼Âå°½æ©æ´é²éÂÂ误æÂÂå©äºÂÃ¥ÂÂå°Â代ç ÂÃ¥ÂÂå¨ BUG çÂÂéÂÂæ£ãÂÂ
ä¸Âè¿Âï¼ÂæÂÂäºÂæ¶åÂÂï¼ÂæÂÂ们就æ¯为äºÂæ¹便æ³è¦Â让ä¸Âé¢çÂÂ示ä¾Â代ç Âè½å¤Âè¿Âè¡Âï¼Âå¯以è¿Âæ ·åÂÂï¼Â
func UnsafeGetUser(db *sqlx.DB) (User, error) {
var user struct {
ID int
Name string
Email string
// 没æ Age å±Âæ§
}
udb := db.Unsafe()
err := udb.Get(&user, "SELECT id, name, email, age FROM user WHERE id = ?", 1)
if err != nil {
return User{}, err
}
return User{
ID: user.ID,
Name: sql.NullString{String: user.Name},
Email: user.Email,
}, nil
}
è¿ÂéÂÂæÂÂ们ä¸ÂÃ¥ÂÂç´æ¥使ç¨ db.Get
æÂ¥æ¥询记å½Âï¼ÂèÂÂæ¯åÂ
ÂéÂÂè¿ udb := db.Unsafe()
è·å unsafe
å±Âæ§为 true
ç *sqlx.DB
对象ï¼Âç¶åÂÂÃ¥ÂÂè°Âç¨å®Âç Get
æ¹æ³ÂãÂÂ
*sqlx.DB
å®Âä¹Âå¦Âä¸Âï¼Â
type DB struct {
*sql.DB
driverName string
unsafe bool
Mapper *reflectx.Mapper
}
å½ unsafe
å±Âæ§为 true
æ¶ï¼Â*sqlx.DB
对象ä¼Â忽çÂ¥ä¸Âå¹éÂ
ÂçÂÂÃ¥ÂÂ段ï¼Â使代ç Âè½å¤Âæ£常è¿Âè¡Âï¼Â并å°Âè½å¤Âå¹éÂ
ÂçÂÂÃ¥ÂÂ段æ£确ç»Âå®Âå° user
ç»ÂæÂÂä½Â对象ä¸ÂãÂÂ
éÂÂè¿Âè¿Â个å±Âæ§çÂÂÃ¥ÂÂ称æÂÂ们就çÂ¥éÂÂï¼Âè¿Âæ¯ä¸Âå®Âå ¨çÂÂÃ¥ÂÂæ³Âï¼Âä¸Â被æ¨èÂÂãÂÂ
ä¸Âæª使ç¨çÂÂÃ¥ÂÂéÂÂä¸Âæ ·ï¼Â被忽çÂ¥çÂÂÃ¥ÂÂæ¯对ç½Âç»ÂÃ¥ÂÂæ°æ®åºÂèµÂæºÂçÂÂ浪费ï¼Â并ä¸Âè¿Âå¾Â容æÂÂ导è´åºç°模åÂÂä¸Âæ°æ®åºÂ表ä¸Âå¹é ÂèÂÂä¸Â被æÂÂçÂ¥çÂÂæ åµãÂÂ
Scan Ã¥ÂÂä½Â
Ã¥ÂÂæÂÂ示ä¾Âä¸Âï¼ÂæÂÂ们è§Âè¿Â亠*sqlx.Rows.Scan
çÂÂÃ¥ÂÂä½ *sqlx.Rows.StructScan
çÂÂç¨æ³Âï¼Âå®Âè½å¤Âæ¹便çÂÂå°Âæ¥询ç»ÂæÂÂæ«æÂÂå° struct
ä¸ÂãÂÂ
sqlx
è¿ÂæÂÂä¾Â亠*sqlx.Rows.MapScan
ãÂÂ*sqlx.Rows.SliceScan
两个æ¹æ³Âï¼Âè½å¤Âå°Âæ¥询ç»ÂæÂÂÃ¥ÂÂå«æ«æÂÂå° map
å slice
ä¸ÂãÂÂ
使ç¨示ä¾Âå¦Âä¸Âï¼Â
func MapScan(db *sqlx.DB) ([]map[string]interface{}, error) {
rows, err := db.Queryx("SELECT * FROM user")
if err != nil {
return nil, err
}
defer rows.Close()
var res []map[string]interface{}
for rows.Next() {
r := make(map[string]interface{})
err := rows.MapScan(r)
if err != nil {
return nil, err
}
res = append(res, r)
}
return res, err
}
func SliceScan(db *sqlx.DB) ([][]interface{}, error) {
rows, err := db.Queryx("SELECT * FROM user")
if err != nil {
return nil, err
}
defer rows.Close()
var res [][]interface{}
for rows.Next() {
// cols is an []interface{} of all the column results
cols, err := rows.SliceScan()
if err != nil {
return nil, err
}
res = append(res, cols)
}
return res, err
}
Ã¥Â
¶ä¸Âï¼Ârows.MapScan(r)
ç¨æ³Â丠rows.StructScan(&u)
ç¨æ³Â类似ï¼Âé½æ¯å°ÂæÂ¥æ¶æ¥询ç»ÂæÂÂéÂÂçÂÂç®æ Â模åÂÂæÂÂéÂÂÃ¥ÂÂéÂÂå½Âä½ÂÃ¥ÂÂæ°传éÂÂè¿ÂæÂ¥ãÂÂ
rows.SliceScan()
ç¨æ³ÂçÂ¥æÂÂä¸ÂÃ¥ÂÂï¼Âå®Âä¸ÂæÂ¥æ¶åÂÂæ°ï¼ÂèÂÂæ¯å°Âç»ÂæÂÂä¿ÂÃ¥ÂÂå¨ []interface{}
ä¸Â并è¿ÂÃ¥ÂÂãÂÂ
å¯以æÂÂéÂÂ使ç¨以ä¸Â两个æ¹æ³ÂãÂÂ
æ§å¶åÂÂ段åÂÂ称æ å°Â
讲å°è¿ÂéÂÂï¼Âæ³å¿Â
ä¸Âå°ÂÃ¥ÂÂå¦å¿ÂéÂÂå¯è½åÂÂå¨ä¸Â个çÂÂæÂÂï¼Ârows.StructScan(&u)
å¨å°Âæ¥询记å½ÂçÂÂÃ¥ÂÂ段æ å°Âå°对åºÂç»ÂæÂÂä½Âå±Âæ§æ¶ï¼Âæ¯å¦Âä½Âæ¾å°对åºÂÃ¥Â
³ç³»çÂÂå¢ï¼Â
çÂÂæ¡Âå°±æ¯ db
ç»ÂæÂÂä½Âæ Âç¾ãÂÂ
Ã¥ÂÂ顾åÂÂæÂÂ讲 声æÂÂ模å æ¶ï¼ÂUser
ç»ÂæÂÂä½Âä¸Âå®Âä¹Âç CreatedAt
ãÂÂUpdatedAt
两个åÂÂ段ï¼Âå®Âä¹Âå¦Âä¸Âï¼Â
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
è¿ÂéÂÂæ¾å¼ÂçÂÂæ ÂæÂÂäºÂç»ÂæÂÂä½Âæ Âç¾ db
ï¼Âsqlx
æ£æ¯使ç¨ db
æ Âç¾æÂ¥æ å°Âæ¥询åÂÂ段åÂÂ模åÂÂå±Âæ§ãÂÂ
é»Â认æÂÂ
åµä¸Âï¼Âç»ÂæÂÂä½ÂÃ¥ÂÂ段ä¼Â被æ å°ÂæÂÂÃ¥Â
¨å°ÂÃ¥ÂÂå½¢å¼Âï¼Â妠ID
Ã¥ÂÂ段ä¼Â被æ å°Â为 id
ï¼Âè CreatedAt
Ã¥ÂÂ段ä¼Â被æ å°Â为 createdat
ãÂÂ
å 为å¨ user
æ°æ®åºÂ表ä¸Âï¼ÂÃ¥ÂÂ建æ¶é´åÂÂæ´æ°æ¶é´两个åÂÂ段åÂÂå«为 created_at
ãÂÂupdated_at
ï¼Â丠sqlx
é»Â认åÂÂ段æ å°Âè§ÂÃ¥ÂÂä¸Âå¹éÂ
Âï¼ÂæÂÂ以æÂÂæÂÂæ¾å¼ÂçÂÂ为 CreatedAt
å UpdatedAt
两个åÂÂ段æÂÂæÂÂ亠db
æ Âç¾ï¼Âè¿Âæ · sqlx
ç rows.StructScan
å°±è½æ£常工ä½ÂäºÂãÂÂ
å½Âç¶ï¼Âæ°æ®åºÂÃ¥ÂÂ段ä¸Âä¸Âå®Âé½æ¯å°ÂÃ¥ÂÂï¼Âå¦ÂæÂÂä½ çÂÂæ°æ®åºÂÃ¥ÂÂ段为åÂ
¨å¤§åÂÂï¼Âsqlx
æÂÂä¾Â亠*sqlx.DB.MapperFunc
æ¹æ³ÂæÂ¥æ§å¶æ¥询åÂÂ段åÂÂ模åÂÂå±Âæ§çÂÂæ å°ÂÃ¥Â
³ç³»ãÂÂ
堶使ç¨示ä¾Âå¦Âä¸Âï¼Â
func MapperFuncUseToUpper(db *sqlx.DB) (User, error) {
copyDB := sqlx.NewDb(db.DB, db.DriverName())
copyDB.MapperFunc(strings.ToUpper)
var user User
err := copyDB.Get(&user, "SELECT id as ID, name as NAME, email as EMAIL FROM user WHERE id = ?", 1)
if err != nil {
return User{}, err
}
return user, nil
}
è¿ÂéÂÂ为äºÂä¸Âæ¹åÂÂÃ¥ÂÂæÂÂç db
对象ï¼ÂæÂÂ们å¤Âå¶äºÂä¸Â个 copyDB
ï¼Âè°Âç¨ copyDB.MapperFunc
并尠strings.ToUpper
ä¼ éÂÂè¿ÂæÂ¥ãÂÂ
注æÂÂè¿ÂéÂÂçÂÂæ¥询è¯Âå¥ä¸Âï¼Âæ¥询åÂÂ段åÂ
¨é¨éÂÂè¿ as
éÂÂæ°å½åÂÂæÂÂäºÂ大åÂÂå½¢å¼Âï¼Âè User
模åÂÂÃ¥ÂÂ段 db
é»Â认é½为å°ÂÃ¥ÂÂå½¢å¼ÂãÂÂ
copyDB.MapperFunc(strings.ToUpper)
çÂÂä½Âç¨ï¼Âå°±æ¯å¨è°Âç¨ Get
æ¹æ³Âå°Âæ¥询ç»ÂæÂÂæ«æÂÂå°ç»ÂæÂÂä½Âæ¶ï¼Âæ User
模åÂÂçÂÂå°ÂÃ¥ÂÂÃ¥ÂÂ段ï¼ÂéÂÂè¿ strings.ToUpper
æ¹æ³Â转æÂÂ大åÂÂï¼Âè¿Âæ ·æ¥询åÂÂ段åÂÂ模åÂÂå±Âæ§就åÂ
¨ä¸ºå¤§åÂÂäºÂï¼Âä¹Âå°±è½å¤Âä¸Âä¸Âå¹éÂ
Âä¸ÂäºÂãÂÂ
è¿ÂæÂÂä¸Âç§ÂæÂÂ
Ã¥Â括Âå¦ÂæÂÂä½ çÂÂ模åÂÂå·²åÂÂå¨ json
æ Âç¾ï¼Â并ä¸Âä¸Âæ³éÂÂå¤ÂçÂÂÃ¥ÂÂæÂÂä¸ÂéÂÂå° db
æ Âç¾ï¼ÂæÂÂ们å¯以ç´æ¥使ç¨ json
æ Âç¾æÂ¥æ å°Âæ¥询åÂÂ段åÂÂ模åÂÂå±Âæ§ãÂÂ
func MapperFuncUseJsonTag(db *sqlx.DB) (User, error) {
copyDB := sqlx.NewDb(db.DB, db.DriverName())
// Create a new mapper which will use the struct field tag "json" instead of "db"
copyDB.Mapper = reflectx.NewMapperFunc("json", strings.ToLower)
var user User
// json tag
err := copyDB.Get(&user, "SELECT id, name as username, email FROM user WHERE id = ?", 1)
if err != nil {
return User{}, err
}
return user, nil
}
è¿ÂéÂÂéÂÂè¦Âç´æ¥修æ¹ copyDB.Mapper
å±Âæ§ï¼ÂèµÂå¼为 reflectx.NewMapperFunc("json", strings.ToLower)
å°Â模åÂÂæ å°ÂçÂÂæ Âç¾ç± db
æ¹为 json
ï¼Â并éÂÂè¿ strings.ToLower
æ¹æ³Â转æ¢为å°ÂÃ¥ÂÂãÂÂ
reflectx
æÂÂçÂ
§å¦Âä¸Âæ¹å¼Â导åÂ
¥ï¼Â
import "github.com/jmoiron/sqlx/reflectx"
ç°å¨ï¼Âæ¥询è¯Âå¥丠name
å±Âæ§éÂÂè¿Â使ç¨ as
被éÂÂå½åÂÂ为 username
ï¼Âè username
Ã¥ÂÂ好丠User
模åÂÂ丠Name
Ã¥ÂÂ段ç json
æ Âç¾ç¸对åºÂï¼Â
Name sql.NullString `json:"username"`
æÂÂ以ï¼Â以ä¸Â示ä¾Â代ç Âè½å¤Âæ£确æ å°Âæ¥询åÂÂ段åÂÂ模åÂÂå±Âæ§ãÂÂ
æ»ç»Â
sqlx
建ç«Âå¨ database/sql
Ã¥ÂÂ
ä¹Âä¸Âï¼Âç¨äºÂç®ÂÃ¥ÂÂÃ¥ÂÂå¢Â强ä¸ÂÃ¥Â
³ç³»åÂÂæ°æ®åºÂçÂÂ交äºÂæÂÂä½ÂãÂÂ
对常è§Âæ°æ®åºÂæÂÂä½Âæ¹æ³Âï¼Âsqlx
æÂÂä¾Â亠Must
çÂÂæ¬ï¼Â妠sqlx.MustOpen
ç¨æÂ¥è¿ÂæÂ¥æ°æ®åºÂï¼Â*sqlx.DB.MustExec
ç¨æÂ¥æ§衠SQL è¯Âå¥ï¼Âå½ÂéÂÂå° error
æ¶å°Âä¼Âç´æÂÂ¥ panic
ãÂÂ
sqlx
è¿Âæ©å±ÂäºÂæ¥询æ¹泠*sqlx.DB.Queryx
ãÂÂ*sqlx.DB.QueryRowx
ãÂÂ*sqlx.DB.Get
ãÂÂ*sqlx.DB.Select
ï¼Â并ä¸Âè¿ÂäºÂæ¥询æ¹æ³Âæ¯æÂÂç´æÂ¥å°Âæ¥询ç»ÂæÂÂæ«æÂÂå°ç»ÂæÂÂä½ÂãÂÂ
sqlx
为 SQL IN æÂÂä½ÂæÂÂä¾ÂäºÂ便æ·æ¹泠sqlx.In
ãÂÂ
为äºÂ使 SQL æ´æÂÂéÂÂ
读ï¼Âsqlx
æÂÂä¾Â亠*sqlx.DB.NamedExec
ãÂÂ*sqlx.DB.NamedQuery
两个æ¹æ³Âæ¯æÂÂÃ¥Â
·åÂÂÃ¥ÂÂæ°ãÂÂ
è°Âç¨ *sqlx.DB.Unsafe()
æ¹æ³Âè½å¤Âè·å unsafe
å±Âæ§为 true
ç *sqlx.DB
对象ï¼Âå¨å°Âæ¥询ç»ÂæÂÂæ«æÂÂå°ç»ÂæÂÂä½Â使å¯以ç¨æ¥忽çÂ¥ä¸Âå¹éÂ
ÂçÂÂè®°å½ÂÃ¥ÂÂ段ãÂÂ
é¤äºÂè½å¤Âå°Âæ¥询ç»ÂæÂÂæ«æÂÂå° struct
ï¼Âsqlx
è¿Âæ¯æÂÂå°Âæ¥询ç»ÂæÂÂæ«æÂÂå° map
å slice
ãÂÂ
sqlx
使ç¨ db
ç»ÂæÂÂä½Âæ Âç¾æÂ¥æ å°Âæ¥询åÂÂ段åÂÂ模åÂÂå±Âæ§ï¼Âå¦ÂæÂÂä¸Âæ¾å¼ÂæÂÂå® db
æ Âç¾ï¼Âé»Â认æ å°ÂçÂÂ模åÂÂå±Âæ§为å°ÂÃ¥ÂÂå½¢å¼Âï¼Âå¯以éÂÂè¿ *sqlx.DB.MapperFunc
å½æ°æ¥修æ¹é»Â认è¡Â为ãÂÂ
æ¾ÂÂå®Âæ´代ç Â示ä¾ÂæÂÂæ¾å¨亠GitHub ä¸Âï¼Â欢è¿Âç¹åÂȾÂ¥çÂÂãÂÂ
å¸ÂæÂÂæ¤æÂÂè½对你æÂÂæÂÂ帮å©ãÂÂ
èÂÂç³»æÂÂ
- 微信ï¼Âjianghushinian
- é®箱ï¼Âjianghushinian007@outlook.com
- Ã¥ÂÂ客å°åÂÂï¼Âjianghushinian.cn/
Ã¥ÂÂèÂÂ
- sqlx æºÂç Âï¼Âgithub.com/jmoiron/sqlâ¦
- sqlx æÂÂæ¡£ï¼Âpkg.go.dev/github.com/â¦
- sqlx å®Âç½Âï¼Âjmoiron.github.io/sqlx/
- æ¾ÂÂ示ä¾Â代ç Âï¼Âgithub.com/jianghushinâ¦