Maison  >  Article  >  base de données  >  Comment connecter Golang à la base de données MySQL

Comment connecter Golang à la base de données MySQL

王林
王林avant
2023-05-26 11:05:511299parcourir

golang exploite mysql

Installation

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

Connexion à la base de données

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

Connexion 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()
}

Types de poignées

La conception SQLx et l'utilisation de la base de données/sql sont les mêmes. Contient 4 types de handles principaux :

  • sqlx.DB - similaire à sql.DB, représentant une base de données.

  • sqlx.Tx - similaire à sql.Tx, représente des choses.

  • sqlx.Stmt - Semblable à sql.Stmt, cela signifie une instruction préparée.

  • sqlx.NamedStmt - représente une instruction préparée (prend en charge les paramètres nommés)

Tous les types de gestionnaires offrent une compatibilité avec database/sql, ce qui signifie que lorsque vous appelez sqlx.DB.Query, vous pouvez le remplacer directement par sql. DB.Query Cela permet d'ajouter facilement sqlx aux projets de base de données existants.

De plus, sqlx a deux types de curseur :

  • sqlx.Rows - Semblable à sql.Rows, Queryx renvoie.

  • sqlx.Row - Semblable à sql.Row, QueryRowx renvoie.

Par rapport à la méthode base de données/sql, elle a une nouvelle syntaxe, ce qui signifie que les données obtenues peuvent être directement converties en structure.

  • Erreur Get(dest interface{}, …)

  • Erreur Select(dest interface{}, …)

Construire une table

Tous les exemples suivants ont la structure de table suivante comme base de fonctionnement.

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 utilise

Exec et MustExec pour supprimer une connexion du pool de connexions, puis exécuter l'opération de requête correspondante. Pour les pilotes qui ne prennent pas en charge l'exécution de requêtes ad hoc, une instruction préparée est créée derrière l'exécution de l'opération. Cette connexion sera renvoyée au pool de connexions avant que le résultat ne soit renvoyé.

Il convient de noter que différents types de bases de données utilisent différents espaces réservés. Qu'utilise MySQL ? comme symbole d'espace réservé.

  • MySQL utilisé ?

  • PostgreSQL utilise 1,1,2 etc.

  • SQLite utilise ? Ou 1 $

  • Oracle Use : name

Exec pour ajouter ou supprimer cet exemple

La syntaxe de requête utilisant Query sera mentionnée plus tard

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

Instructions préparées SQL

Pour la plupart des bases de données, lorsqu'une requête est exécutée , l'instruction dans la base de données d'instructions SQL a été déclarée. L'instruction est dans la base de données. Nous pouvons la déclarer à l'avance afin qu'elle puisse être réutilisée à d'autres endroits.

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)

Bien sûr, sqlx fournit également Preparex() pour l'expansion, qui peut être directement utilisé pour la conversion de structure

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

Query

les résultats des lignes sont obtenus en utilisant les lignes dans la base de données/sql. La requête renvoie un objet sql.Rows et un objet d'erreur.

Lorsque vous l'utilisez, vous devez traiter les lignes comme un curseur au lieu d'une série de résultats. Bien que les méthodes de mise en cache basée sur la base de données soient différentes, une colonne de résultats est obtenue à chaque fois via l'itération Next(). Lorsque les résultats de la requête sont très volumineux, l'utilisation de la mémoire peut être efficacement limitée par Scan() pour mapper chaque colonne. des résultats SQL à parcourir. Types de données de langage tels que chaîne, [] octet, etc. Si vous ne parcourez pas tous les résultats des lignes, veillez à appeler rows.Close() avant de renvoyer la connexion au pool de connexions.

L'erreur renvoyée par Query peut se produire lorsque le serveur prépare la requête, ou elle peut se produire lorsque l'instruction de requête est exécutée. Par exemple, même si la base de données essaie 10 fois de trouver ou de créer une connexion disponible, il est possible d'obtenir une mauvaise connexion à partir du pool de connexions. Habituellement, les erreurs proviennent principalement d’erreurs dans les instructions SQL, d’erreurs de correspondance similaires et d’erreurs dans les noms de domaines ou de tables.

Dans la plupart des cas, Rows.Scan() fera une copie des données obtenues à partir du pilote, quelle que soit la manière dont le pilote utilise le cache. Le type spécial sql.RawBytes peut être utilisé pour obtenir un octet de tranche sans copie à partir des données renvoyées par le pilote. La prochaine fois que Next sera appelé, la valeur ne sera pas valide car la mémoire vers laquelle elle pointe a été écrasée par le pilote avec d'autres données.

La connexion utilisée par Query est libérée une fois que toutes les lignes ont été parcourues via Next() ou après l'appel de rows.Close().

Exemple :

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 se comporte de manière très similaire à Query, mais renvoie un objet sqlx.Rows, prend en charge le comportement d'analyse étendu et peut effectuer une conversion de structure sur les données.

Exemple :

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 et QueryRowx

QueryRow et QueryRowx obtiennent tous deux une donnée de la base de données, mais QueryRowx fournit une extension d'analyse qui peut directement convertir les résultats en une structure.

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}

Get and Select (très couramment utilisé)

Get and Select est une extension très rapide qui peut attribuer directement le résultat à la structure, et elle encapsule StructScan en interne pour la conversion. Utilisez la méthode Get pour obtenir un résultat unique, puis utilisez la méthode Scan et utilisez la méthode Select pour obtenir des tranches de résultats.

Exemple :

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}

Transactions

Les opérations de transaction sont mises en œuvre via trois méthodes :

Begin() : ouvrir la transaction

Commit() : valider la transaction (exécuter SQL)

Rollback() : revenir en arrière

Processus d'utilisation :

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)
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer