Mysql and Redis operations
Mysql development
- Install mysql and create test library
- Create table
mysql> CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT '', `age` int(11) DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; mysql> insert into user (name,age)values('jim',18)
SQL query
- Single line query: Db.QueryRole
- Multiline query: Db.Query
import ( "fmt" _"github.com/go-sql-driver/mysql" "database/sql" ) type User struct { Id int64 `db:"id"` Name string `db:"name"` Age int `db:"age"` } func connMysql() { dns := "root:123456@tcp(localhost:3306)/test" conn,err := sql.Open("mysql",dns) if err != nil { fmt.Printf("connect mysql err:%v\n",err) return } err = conn.Ping() if err != nil { fmt.Printf("ping faild,err :%v\n",err) } fmt.Printf("connect mysql successfully!\n") QueryRow(conn) Query(conn) defer conn.Close() } func QueryRow(Db *sql.DB) { id := 1 //Single line data query row := Db.QueryRow("select id,name,age from user where id=?",id) var user User err := row.Scan(&user.Id,&user.Name,&user.Age) if err == sql.ErrNoRows { fmt.Printf("not found data by id:%v\n",id) } if err != nil { fmt.Printf("scan faild,err: %v\n",err) return } fmt.Printf("user:%#v\n",user) } func Query(Db *sql.DB) { id := 0 //Multi row data query rows,err := Db.Query("select id,name,age from user where id>?",id) //Be sure to close the result set defer func() { if rows != nil { rows.Close() } }() //Query exception capture if err == sql.ErrNoRows { fmt.Printf("not found data by id:%v\n",id) } if err != nil { fmt.Printf("scan faild,err: %v\n",err) return } //Traverse all data for rows.Next() { var user User err := rows.Scan(&user.Id,&user.Name,&user.Age) if err == sql.ErrNoRows { fmt.Printf("not found data by id:%v\n",id) } if err != nil { fmt.Printf("scan faild,err: %v\n",err) return } fmt.Printf("user:%#v\n",user) } } func main() { connMysql() }
Mysql insert update and delete
- Use DB.Exec()
import ( "fmt" _"github.com/go-sql-driver/mysql" "database/sql" ) type User struct { Id int64 `db:"id"` Name string `db:"name"` Age int `db:"age"` } func Insert(DB *sql.DB) { username := "alex" age := 18 result,err := DB.Exec("insert into user(name,age) values(?,?)",username,age) if err != nil { fmt.Printf("sql exec insert faild:err:%v\n",err) return } id,err := result.LastInsertId() if err != nil { fmt.Printf("last insert id faild,err:%v\n",err) return } affectRows,err := result.RowsAffected() if err != nil { fmt.Printf("Rows affects faild,err:%v\n",err) return } fmt.Printf("last insert id:%d, affect rows:%d\n",id,affectRows) } func Update(DB *sql.DB) { username := "bbq" age := 12 result,err := DB.Exec("update user set name=?,age=? where id=?",username,age,3) if err != nil { fmt.Printf("sql exec update faild:err:%v\n",err) return } affectRows,err := result.RowsAffected() if err != nil { fmt.Printf("Rows affects faild,err:%v\n",err) return } fmt.Printf("affect rows:%d\n",affectRows) } func Delete(DB *sql.DB) { id := 5 result,err := DB.Exec("delete from user where id=?",id) if err != nil { fmt.Printf("sql exec delete faild:err:%v\n",err) return } affectRows,err := result.RowsAffected() if err != nil { fmt.Printf("Rows affects faild,err:%v\n",err) return } fmt.Printf("affect rows:%d\n",affectRows) } func connMysql() { dns := "root:123456@tcp(localhost:3306)/test" conn,err := sql.Open("mysql",dns) if err != nil { fmt.Printf("connect mysql err:%v\n",err) return } err = conn.Ping() if err != nil { fmt.Printf("ping faild,err :%v\n",err) } fmt.Printf("connect mysql successfully!\n") //QueryRow(conn) //Query(conn) //Insert(conn) //Update(conn) Delete(conn) defer conn.Close() }
mysql preprocessing
-
General sql processing flow
- The client splices the sql statements
- Client sends sql statement to mysql server
- The mysql server parses the sql statement and executes it, returning the output to the client
-
Pretreatment process
- Split sql into two parts, command part and data part
- First, send the command part to mysql server for sql preprocessing
- Then send the data part to mysql server for placeholder replacement
- mysql executes the sql statement and returns the result to the client
- Advantages of pretreatment
- If the same sql is executed repeatedly, the performance will be very high
- Avoid sql injection problems
Pretreatment example
- Query operation
- Db.Prepare(sql string)(*sql.Stmt,error)
- Stmt.Query()
func PrepareQuery(DB *sql.DB) { //Part 1: sending commands and placeholders stmt,err := DB.Prepare("select id,name,age from user where id>?") if err != nil { fmt.Printf("prepare faild,error:%v\n",err) return } //Part two: sending data and executing sql id := 1 rows,err := stmt.Query(id) //Be sure to close the result set defer func() { if rows != nil { rows.Close() } if stmt != nil { stmt.Close() } }() //Query exception capture if err == sql.ErrNoRows { fmt.Printf("not found data by id:%v\n",id) } if err != nil { fmt.Printf("scan faild,err: %v\n",err) return } //Traverse all data for rows.Next() { var user User err := rows.Scan(&user.Id,&user.Name,&user.Age) if err == sql.ErrNoRows { fmt.Printf("not found data by id:%v\n",id) } if err != nil { fmt.Printf("scan faild,err: %v\n",err) return } fmt.Printf("user:%#v\n",user) } }
- Update operation (insert, update, delete)
- Db.Prepare(sql string)(*sql.Stmt,error)
- Stmt.Exec()
func PrepareInsert(DB *sql.DB) { //Part 1: sending commands and placeholders stmt,err := DB.Prepare("insert into user (name,age) values (?,?);") if err != nil { fmt.Printf("prepare faild,error:%v\n",err) return } //Part two: sending data and executing sql username := "zhangqiqi" age := 29 result,err := stmt.Exec(username,age) if err != nil { fmt.Printf("sql exec insert faild:err:%v\n",err) return } id,err := result.LastInsertId() if err != nil { fmt.Printf("last insert id faild,err:%v\n",err) return } affectRows,err := result.RowsAffected() if err != nil { fmt.Printf("Rows affects faild,err:%v\n",err) return } fmt.Printf("last insert id:%d, affect rows:%d\n",id,affectRows) }
mysql transaction instance
- Ensure data consistency
- Transaction operation of mysql
- DB.Begin() start transaction
- DB.Commit() commit transaction
- DB.Roback() rollback transaction
func Transaction(DB *sql.DB) { tx,err := DB.Begin() if err != nil { fmt.Printf("begin faild,err:%v\n",err) return } _,err = tx.Exec("insert into user (name,age)values (?,?)","jemmy",80) if err != nil { tx.Rollback() return } _,err = tx.Exec("update user set name=?,age=? where id=6","jemmxiny",60) if err != nil { tx.Rollback() return } err = tx.Commit() if err != nil { tx.Rollback() //Rollback if data exception occurs return } }
Introduction and use of sqlx Library
-
Features of sqlx:
- Easier to use
- Support for database, mysql,postgresql,oracle,sqlit
- The use of sqlx
- Query: sqlx.DB.Get and sqlx.DB.Select
- Update, insert and delete: sqlx.DB.Exex()
- Transaction: sqlx.DB.Begin(),sqlx.DB.Commit(),sqlx.DB.Rollback
go get github.com/jmoiron/sqlx
Using examples
import ( "database/sql" "fmt" "github.com/jmoiron/sqlx" _ "github.com/go-sql-driver/mysql" ) type User struct { Id int64 `db:"id"` Name string `db:"name"` Age int `db:"age"` } func connMysql() { dns := "root:123456@tcp(localhost:3306)/test" conn,err := sqlx.Connect("mysql",dns) if err != nil { fmt.Printf("connect mysql err:%v\n",err) return } //Timeout tests err = conn.Ping() if err != nil { fmt.Printf("ping faild,err :%v\n",err) } fmt.Printf("connect mysql successfully!\n") //Close connection //QueryRow(conn) //Query(conn) Insert(conn) defer conn.Close() } func QueryRow(Db *sqlx.DB) { id := 100 //Single line data query var user User err := Db.Get(&user,"select id,name,age from user where id=?",id) //Blank data if err == sql.ErrNoRows { fmt.Printf("no record to found\n") return } if err != nil { fmt.Printf("get faild,err:%v\n",err) return } fmt.Printf("user:%#v\n",user) } func Query(Db *sqlx.DB) { var user []*User id := 1 //Multi row data query err := Db.Select(&user,"select id, name, age from user where id>?",id) if err == sql.ErrNoRows { fmt.Printf("no record found\n") return } if err != nil { fmt.Printf("select rows faild,err:%v\n",err) return } //Output query results fmt.Printf("user:%#v\n",user) for _,v := range user { fmt.Printf("%v\n",v) } } func Insert(Db *sqlx.DB) { username := "alex" age := 18 result,err := Db.Exec("insert into user(name,age) values(?,?)",username,age) if err != nil { fmt.Printf("sql exec insert faild:err:%v\n",err) return } id,err := result.LastInsertId() if err != nil { fmt.Printf("last insert id faild,err:%v\n",err) return } affectRows,err := result.RowsAffected() if err != nil { fmt.Printf("Rows affects faild,err:%v\n",err) return } fmt.Printf("last insert id:%d, affect rows:%d\n",id,affectRows) } func main() { connMysql() }
Redis development
- Using a third-party library: github.com/garyburd/rediso/redis
Use of redis
func initRedis() (conn redis.Conn,err error) { conn,err = redis.Dial("tcp","127.0.0.1:6379") if err != nil { fmt.Printf("conn redis error:%v\n",err) return } fmt.Printf("conn redis succ\n") return } func testSetGet(conn redis.Conn) { key := "abc" _,err := conn.Do("set",key,"this is a test!") if err != nil { fmt.Printf("set value faild,eror:%v\n",err) return } data,err := redis.String(conn.Do("get",key)) if err != nil { fmt.Printf("get faild,err:%v\n",err) return } fmt.Printf("key:%s, value:%v\n",key,data) } func main() { conn,err := initRedis() if err != nil { return } testSetGet(conn) }
Hash table operation
func testSetGet(conn redis.Conn) { key := "abc" _,err := conn.Do("hset","books",key,"this is a test!") if err != nil { fmt.Printf("set value faild,eror:%v\n",err) return } data,err := redis.String(conn.Do("hget","books",key)) if err != nil { fmt.Printf("get faild,err:%v\n",err) return } fmt.Printf("key:%s, value:%v\n",key,data) }
Redis concurrent operation
func testMSetGet(conn redis.Conn) { key := "abc" key1 := "def" _,err := conn.Do("mset",key,key1) if err != nil { fmt.Printf("set value faild,eror:%v\n",err) return } //Data returned by multi value operation is received with strings data,err := redis.Strings(conn.Do("mget",key,key1)) if err != nil { fmt.Printf("get faild,err:%v\n",err) return } //Cycle value for _,val := range data { fmt.Printf("key:%s, value:%v\n",key,val) } }
Setup queue
Publish subscribe
func testQuenu(conn redis.Conn) { _,err := conn.Do("lpush","book_list","this is a test!","daadada") if err != nil { fmt.Printf("lpush value faild,eror:%v\n",err) return } data,err := redis.String(conn.Do("rpop","book_list")) if err != nil { fmt.Printf("get faild,err:%v\n",err) return } fmt.Printf("value:%s\n",data) }
Connection pool
func newPool(serverAddr string,passwd string) (pool *redis.Pool) { return &redis.Pool{ MaxIdle: 16, MaxActive: 1024, IdleTimeout: 240, Dial: func() (redis.Conn,error) { conn,err := redis.Dial("tcp",serverAddr) if err != nil { return nil,err } if len(passwd) > 0 { _,err := conn.Do("auth",passwd) if err != nil { return nil,err } } return conn,err }, TestOnBorrow: func(c redis.Conn,t time.Time) error { if time.Since(t) < time.Minute { return nil } _,err := c.Do("ping") return err }, } } func testRedisPool() { pool := newPool("127.0.0.1:6379","") conn := pool.Get() conn.Do("set","abcd","23134534665437372132") val,err := redis.String(conn.Do("get","abcd")) if err != nil { fmt.Printf("get faild,err:%v\n",err) } fmt.Printf("val:%v,err:%v\n",val,err) //Return connection to connection pool conn.Close() }