Rumah  >  Artikel  >  pangkalan data  >  Bagaimana untuk menyambung golang ke pangkalan data mysql

Bagaimana untuk menyambung golang ke pangkalan data mysql

王林
王林ke hadapan
2023-05-26 11:05:511299semak imbas

golang operation mysql

Pemasangan

go get "github.com/go-sql-driver/mysql"
go get "github.com/jmoiron/sqlx"

Sambung ke pangkalan data

var Db *sqlx.DB
db, err := sqlx.Open("mysql","username:password@tcp(ip:port)/database?charset=utf8")
Db = db

Sambung 2

package main
import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB  //全局对象db

func initDB() (err error) {
  db, err = sql.Open("mysql","root:admin123@tcp(127.0.0.1:3306)/dududu?charset=utf8")
  if err!=nil{
    return err
  }
  err = db.Ping()  //校验数据库连接
  if err!=nil{
    return err
  }
  return nil
}

type beautiful struct {
	spu_id string
	title string
	price string
}

func queryRowDemo()  {
	sqlStr :="select spu_id,title,price from dududu_shops where id = ?"
	var u beautiful
	err:=db.QueryRow(sqlStr,101).Scan(&u.spu_id,&u.title,&u.price)
	if err!=nil{
		fmt.Println("2",err)
	}
	fmt.Println(u)
}


func main()  {
	err:=initDB()
	if err!=nil{
		fmt.Println("1",err)
		return
	}
	queryRowDemo()
}

Jenis Pengendalian

Reka bentuk sqlx dan kaedah penggunaan pangkalan data/sql adalah sama. Mengandungi 4 jenis pemegang utama:

  • sqlx.DB - serupa dengan sql.DB, mewakili pangkalan data.

  • sqlx.Tx - serupa dengan sql.Tx, mewakili sesuatu.

  • sqlx.Stmt - Sama seperti sql.Stmt, ia mewakili pernyataan yang disediakan.

  • sqlx.NamedStmt - mewakili pernyataan yang disediakan (menyokong parameter bernama)

Semua jenis pengendali menyediakan keserasian dengan pangkalan data/sql, Ini bermakna apabila anda memanggil sqlx.DB.Query, anda boleh menggantikannya secara langsung dengan sql.DB.Query Ini menjadikan sqlx mudah untuk ditambahkan pada projek pangkalan data sedia ada.

Selain itu, sqlx mempunyai dua jenis kursor:

  • sqlx.Rows - Sama seperti sql.Rows, Queryx kembali.

  • sqlx.Row - Sama seperti sql.Row, QueryRowx kembali.

Berbanding dengan kaedah pangkalan data/sql, terdapat sintaks baru, yang bermaksud bahawa data yang diperolehi boleh terus ditukar kepada struktur.

  • Dapatkan(antara muka akhir{}, …) ralat

  • Ralat pilih(antara muka akhir{}, …)

Mencipta jadual

Semua contoh berikut menggunakan struktur jadual berikut sebagai asas untuk operasi.

CREATE TABLE `userinfo` (
    `uid` INT(10) NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(64)  DEFAULT NULL,
    `password` VARCHAR(32)  DEFAULT NULL,
    `department` VARCHAR(64)  DEFAULT NULL,
    `email` varchar(64) DEFAULT NULL,
    PRIMARY KEY (`uid`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8

Exec menggunakan

Exec dan MustExec untuk mengeluarkan sambungan daripada kumpulan sambungan dan kemudian melaksanakan operasi pertanyaan yang sepadan. Untuk pemandu yang tidak menyokong pelaksanaan pertanyaan ad-hoc, pernyataan yang disediakan dibuat di sebalik pelaksanaan operasi. Sambungan ini akan dikembalikan ke kolam sambungan sebelum hasilnya dikembalikan.

Perlu diingatkan bahawa jenis pangkalan data yang berbeza menggunakan ruang letak yang berbeza Apakah yang digunakan oleh mysql? sebagai simbol pemegang tempat.

  • MySQL digunakan?

  • PostgreSQL menggunakan 1,1,2 dsb.

  • SQLite menggunakan? Atau $1

  • Oracle Use: name

Exec untuk menambah atau memadam contoh ini

Sintaks pertanyaan menggunakan Query akan disebut nanti

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
    "fmt"
)

var Db *sqlx.DB

func init()  {
    db, err := sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = db
}

func main()  {
    result, err := Db.Exec("INSERT INTO userinfo (username, password, department,email) VALUES (?, ?, ?,?)","wd","123","it","wd@163.com")
    if err != nil{
        fmt.Println("insert failed,error: ", err)
        return
    }
    id,_ := result.LastInsertId()
    fmt.Println("insert id is :",id)
    _, err1 := Db.Exec("update userinfo set username = ? where uid = ?","jack",1)
    if err1 != nil{
        fmt.Println("update failed error:",err1)
    } else {
        fmt.Println("update success!")
    }
    _, err2 := Db.Exec("delete from userinfo where uid = ? ", 1)
    if err2 != nil{
        fmt.Println("delete error:",err2)
    }else{
        fmt.Println("delete success")
    }

}
//insert id is : 1
//update success!
//delete success

sql Prepared Statements

Bagi kebanyakan pangkalan data, apabila pertanyaan dilaksanakan, pernyataan di dalam pangkalan data pernyataan sql telah pun diisytiharkan, dan pernyataannya berada dalam pangkalan data, kami boleh mengisytiharkan ia lebih awal daripada masa untuk digunakan semula di tempat lain.

stmt, err := db.Prepare(`SELECT * FROM place WHERE telcode=?`)
row = stmt.QueryRow(65)
 
tx, err := db.Begin()
txStmt, err := tx.Prepare(`SELECT * FROM place WHERE telcode=?`)
row = txStmt.QueryRow(852)

Sudah tentu sqlx juga menyediakan Preparex() untuk pengembangan, yang boleh digunakan terus untuk penukaran struktur

stmt, err := db.Preparex(`SELECT * FROM place WHERE telcode=?`)
var p Place
err = stmt.Get(&p, 852)

Query

hasil baris diperoleh dengan menggunakan Rows dalam pangkalan data/ sql Dapatkan. Pertanyaan mengembalikan objek sql.Rows dan objek ralat.

Apabila menggunakannya, Rows harus dianggap sebagai kursor dan bukannya satu siri hasil. Walaupun kaedah caching dipacu pangkalan data adalah berbeza, satu lajur hasil diperoleh setiap kali melalui lelaran Next() Apabila hasil pertanyaan adalah sangat besar, penggunaan memori boleh dihadkan dengan berkesan untuk memetakan setiap lajur daripada hasil SQL untuk pergi jenis data bahasa seperti rentetan, []bait, dsb. Jika anda tidak mengulangi semua hasil baris, pastikan anda memanggil rows.Close() sebelum mengembalikan sambungan ke kolam sambungan.

Ralat yang dikembalikan oleh Pertanyaan mungkin berlaku apabila pelayan menyediakan pertanyaan, atau ia mungkin berlaku apabila pernyataan pertanyaan dilaksanakan. Sebagai contoh, walaupun pangkalan data cuba 10 kali untuk mencari atau mencipta sambungan yang tersedia, adalah mungkin untuk mendapatkan sambungan yang buruk daripada kumpulan sambungan. Biasanya, ralat terutamanya berpunca daripada ralat dalam pernyataan SQL, ralat padanan serupa dan ralat dalam nama domain atau nama jadual.

Dalam kebanyakan kes, Rows.Scan() akan membuat salinan data yang diperoleh daripada pemandu, tanpa mengira cara pemandu menggunakan cache. Jenis sql.RawBytes khas boleh digunakan untuk mendapatkan bait hirisan salinan sifar daripada data yang dikembalikan oleh pemandu. Kali seterusnya Next dipanggil, nilai akan menjadi tidak sah kerana memori yang ditunjuknya telah ditimpa oleh pemacu dengan data lain.

Sambungan yang digunakan oleh Query dikeluarkan selepas semua baris dilalui melalui Next() atau selepas baris.Close() dipanggil.

Contoh:

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
    "fmt"
)

var Db *sqlx.DB

func init()  {
    db, err := sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = db
}

func main()  {
    rows, err := Db.Query("SELECT username,password,email FROM userinfo")
    if err != nil{
        fmt.Println("query failed,error: ", err)
        return
    }
    for rows.Next() {  //循环结果
        var username,password,email string
        err = rows.Scan(&username, &password, &email)
        println(username,password,email)
    }
    
}
//wd 123 wd@163.com
//jack 1222 jack@165.com

Queryx

Queryx berkelakuan sangat serupa dengan Query, tetapi mengembalikan objek sqlx.Rows, menyokong gelagat imbasan lanjutan dan boleh menstrukturkan penukaran badan data .

Contoh:

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
    "fmt"
)

var Db *sqlx.DB

type stu struct {
    Username string   `db:"username"`
    Password string      `db:"password"`
    Department string  `db:"department"`
    Email string        `db:"email"`
}

func init()  {
    db, err := sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = db
}

func main()  {
    rows, err := Db.Queryx("SELECT username,password,email FROM userinfo")
    if err != nil{
        fmt.Println("Qeryx failed,error: ", err)
        return
    }
    for rows.Next() {  //循环结果
        var stu1 stu
        err = rows.StructScan(&stu1)// 转换为结构体
        fmt.Println("stuct data:",stu1.Username,stu1.Password)
    }
}
//stuct data: wd 123
//stuct data: jack 1222

QueryRow dan QueryRowx

QueryRow dan QueryRowx kedua-duanya memperoleh sekeping data daripada pangkalan data, tetapi QueryRowx menyediakan sambungan imbasan yang boleh menukar hasil secara terus kepada sebuah struktur.

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
    "fmt"
)

var Db *sqlx.DB

type stu struct {
    Username string   `db:"username"`
    Password string      `db:"password"`
    Department string  `db:"department"`
    Email string        `db:"email"`
}

func init()  {
    db, err := sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = db
}

func main()  {
    row := Db.QueryRow("SELECT username,password,email FROM userinfo where uid = ?",1) // QueryRow返回错误,错误通过Scan返回
    var username,password,email string
    err :=row.Scan(&username,&password,&email)
    if err != nil{
        fmt.Println(err)
    }
    fmt.Printf("this is QueryRow res:[%s:%s:%s]\n",username,password,email)
    var s stu
    err1 := Db.QueryRowx("SELECT username,password,email FROM userinfo where uid = ?",2).StructScan(&s)
    if err1 != nil{
        fmt.Println("QueryRowx error :",err1)
    }else {
        fmt.Printf("this is QueryRowx res:%v",s)
    }
}
//this is QueryRow res:[wd:123:wd@163.com]
//this is QueryRowx res:{jack 1222  jack@165.com}

Dapatkan dan Pilih (sangat biasa digunakan)

Dapatkan dan Pilih ialah sambungan yang sangat menjimatkan masa yang boleh memberikan hasil secara langsung kepada struktur, dan ia merangkumi StructScan secara dalaman untuk penukaran. Gunakan kaedah Dapatkan untuk mendapatkan hasil tunggal dan kemudian gunakan kaedah Imbas, dan gunakan kaedah Pilih untuk mendapatkan kepingan hasil.

Contoh:

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
    "fmt"
)

var Db *sqlx.DB

type stu struct {
    Username string   `db:"username"`
    Password string      `db:"password"`
    Department string  `db:"department"`
    Email string        `db:"email"`
}

func init()  {
    db, err := sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = db
}

func main()  {
    var stus []stu
    err := Db.Select(&stus,"SELECT username,password,email FROM userinfo")
    if err != nil{
        fmt.Println("Select error",err)
    }
    fmt.Printf("this is Select res:%v\n",stus)
    var s stu
    err1 := Db.Get(&s,"SELECT username,password,email FROM userinfo where uid = ?",2)
    if err1 != nil{
        fmt.Println("GET error :",err1)
    }else {
        fmt.Printf("this is GET res:%v",s)
    }
}
//this is Select res:[{wd 123  wd@163.com} {jack 1222  jack@165.com}]
//this is GET res:{jack 1222  jack@165.com}

Transaksi

Operasi transaksi dilaksanakan melalui tiga kaedah:

Begin(): Mulakan transaksi

Komit (): Hantar transaksi (laksana sql)

Rollback(): Rollback

Proses penggunaan:

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

//或者使用sqlx扩展的事务
tx := db.MustBegin()
tx.MustExec(...)
err = tx.Commit()

为了维持一个持续的连接状态,Tx对象必须绑定和控制单个连接。在整个生命周期期间,一个Tx将保持连接,直到调用commit或Rollback()方法将其释放。必须非常谨慎地调用这些函数,否则连接将一直被占用,直到被垃圾回收。

使用示例:

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
    "fmt"
)

var Db *sqlx.DB

func init()  {
    db, err := sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = db
}

func main()  {
    tx, err := Db.Beginx()
    _, err = tx.Exec("insert into userinfo(username,password) values(?,?)", "Rose","2223")
    if err != nil {
        tx.Rollback()
    }
    _, err = tx.Exec("insert into userinfo(username,password) values(?,?)", "Mick",222)
    if err != nil {
        fmt.Println("exec sql error:",err)
        tx.Rollback()
    }
    err = tx.Commit()
    if err != nil {
        fmt.Println("commit error")
    }

}

连接池设置

当连接池中没有可用空闲连接时,连接池会自动创建连接,并且其增长是无限制的。最大连接数可以通过调用DB.SetMaxOpenConns来设置。未使用的连接标记为空闲,如果不需要则关闭。为了减少连接的开启和关闭次数,可以利用DB.SetMaxIdleConns方法来设定最大的空闲连接数。

注意:该设置方法golang版本至少为1.2

  • DB.SetMaxIdleConns(n int) 设置最大空闲连接数

  • DB.SetMaxOpenConns(n int) 设置最大打开的连接数

  • DB.SetConnMaxIdleTime(time.Second*10) 间隔时间

示例:

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
    "fmt"
)

var Db *sqlx.DB

func init()  {
    db, err := sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = db
    Db.SetMaxOpenConns(30)
    Db.SetMaxIdleConns(15)

}

案例使用

var Db *sqlx.DB
db, err := sqlx.Open("mysql","root:admin123@tcp(127.0.0.1:3306)/dududu?charset=utf8")
Db = db

rows, err := Db.Query("SELECT spu_id,title,price FROM dududu_shops")

if err != nil{
  fmt.Println("query failed,error: ", err)
  return
}
for rows.Next() {  //循环结果
  var spu_id,title,price string
  err = rows.Scan(&spu_id, &title, &price)
  println(spu_id,title,price)
}

Atas ialah kandungan terperinci Bagaimana untuk menyambung golang ke pangkalan data mysql. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam