go 語言操作 MySQL 範例

MySQL 本身的相關知識:
http://www.runoob.com/mysql/mysql-transaction.html
https://blog.longwin.com.tw/2006/03/innodb_transaction_2006/
https://xyz.cinc.biz/2013/05/mysql-transaction.html

Golang 操作相關知識:
https://ithelp.ithome.com.tw/articles/10207409
https://segmentfault.com/a/1190000003036452

https://www.jianshu.com/p/bc8120bec94e
http://hopehook.com/2017/08/21/golang_transaction/
https://www.cnblogs.com/hupengcool/p/4143238.html
https://www.kancloud.cn/liupengjie/go/570128

* 事務處理 ( transaction )

tx, err := db.Begin()
...
...
...

tx.Commit()


* tx对象

一般查询使用的是db对象的方法,事务则是使用另外一个对象。sql.Tx对象。使用db的Begin方法可以创建tx对象。tx对象也有数据库交互的Query,Exec和Prepare方法。用法和db的相关用法类似。查询或修改的操作完毕之后,需要调用tx对象的Commit提交或者Rollback方法回滚。

一旦创建了tx对象,事务处理都依赖与tx对象,这个对象会从连接池中取出一个空闲的连接,接下来的sql执行都基于这个连接,直到commit或者rollback调用之后,才会把连接释放到连接池。

在事务处理的时候,不能使用db的查询方法,虽然后者可以获取数据,可是这不属于同一个事务处理,将不会接受commit和rollback的改变,一个简单的事务例子如下:

tx, err := db.Begin()
tx.Exec(query1)
tx.Exec(query2)
tx.Commit()

在tx中使用db是错误的:

tx, err := db.Begin()
db.Exec(query1)
tx.Exec(query2)
tx.commit()

上述代码在调用db的Eexc方法的时候,tx会绑定连接到事务中,db则是额外的一个连接,两者不是同一个事务。需要注意,Begin和Commit方法,与 sql 语句中的 BEGIN 或 COMMIT 语句没有关系。

關於事務的相關細節應該詳閱 https://www.jianshu.com/p/bc8120bec94e
涉及到 Transaction 事务、tx对象、事务与连接、事务并发、实践。


* 如果在rows遍历结束之前退出循环,必须手动关闭Resultset,并且接收error。

for rows.Next() {
    // ...
    break; // whoops, rows is not closed! memory leak...
}
// do the usual "if err = rows.Err()" [omitted here]...
// it's always safe to [re?]close here:
if err = rows.Close(); err != nil {
    // but what should we do if there's an error?
    log.Println(err)
}


* 如果id为1的不存在,err为sql.ErrNoRows,一般应用中不存在的情况都需要单独处理。此外,Query返回的错误都会延迟到Scan被调用,所以应该写成如下代码:

var name string
err = db.QueryRow("select name from users where id = ?", 1).Scan(&name)
if err != nil {
    if err == sql.ErrNoRows {
        // there were no rows, but otherwise no error occurred
        // 把空结果当做Error处理是为了强行让程序员处理结果为空的情况
    } else {
        log.Fatal(err)
    }
}
fmt.Println(name)




https://blog.csdn.net/jesseyoung/article/details/40398321
https://studygolang.com/articles/5402

go官方仅提供了database package,database package下有两个包sql,sql/driver。这两个包用来定义操作数据库的接口,这就保证了无论使用哪种数据库,他们的操作方式都是相同的。
    但go官方并没有提供连接数据库的driver,如果要操作数据库,还需要第三方的driver 包,最常用的有:
    https://github.com/Go-SQL-Driver/MySQL支持database/sql,全部采用go写。
    https://github.com/ziutek/mymysql 支持database/sql,也支持自定义的接口,全部采用go写。
    推荐使用前者,因为前者的效率更高一点,二者效率的对比可参考benchmark测试结果:https://github.com/go-sql-driver/sql-benchmark

    go连接其他主流数据库的驱动介绍可参考:
    https://code.google.com/p/go-wiki/wiki/SQLDrivers


user:password@tcp(localhost:5555)/dbname?charset=utf8&autocommit=true
user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?charset=utf8mb4




golang 的 包 還不支援 MySQL 8 以上的一個新特性,所以需要如下措施:
https://blog.pilipala.co/articles/2019/02/14/1550128481833

mysql 在 8.0 之后将用户使用的 plugin 更新成 caching_sha2_password。而在之前用的是 mysql_native_password。

在 MySQL 內
use mysql;
select user,host,plugin from user;

可以看到相關資訊

接著利用修改密碼的語法順便將 root 從 caching_sha2_password 改回到 mysql_native_password

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

最後需要再將 golang 內的連結語法加上一個參數 &allowNativePasswords=true

user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?charset=utf8mb4&allowNativePasswords=true

程式語言編年史

程式語言編年史原文 下面這張圖片描繪了整個程式語言的歷史。包括各種程式語言的發明人、程式語言的特點和適用領域、被什麼網站或公司使用等 (檢視 完整高清圖 )。 之所以會有那麼多不同的程式語言是因為設計程式語言的初衷不同、對語言學習曲線的追求不同、不同程式之間的執行成本差異...