>  기사  >  데이터 베이스  >  mysql 데이터베이스에 golang을 연결하는 방법

mysql 데이터베이스에 golang을 연결하는 방법

王林
王林앞으로
2023-05-26 11:05:511298검색

golang은 mysql을 운영합니다

설치

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

데이터베이스에 연결

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

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

Handle Types

sqlx 디자인과 데이터베이스/sql 사용법은 동일합니다. 4가지 주요 핸들 유형을 포함합니다:

  • sqlx.DB - 데이터베이스를 나타내는 sql.DB와 유사합니다.

  • sqlx.Tx - sql.Tx와 유사하며 사물을 나타냅니다.

  • sqlx.Stmt - sql.Stmt와 유사하며 준비된 문을 의미합니다.

  • sqlx.NamedStmt - 준비된 문을 나타냅니다(이름이 지정된 매개변수 지원).

모든 핸들러 유형은 데이터베이스/sql과의 호환성을 제공하므로 sqlx.DB.Query를 호출할 때 이를 sql로 직접 대체할 수 있습니다. DB.Query를 사용하면 기존 데이터베이스 프로젝트에 sqlx를 쉽게 추가할 수 있습니다.

또한 sqlx에는 두 가지 커서 유형이 있습니다.

  • sqlx.Rows - sql.Rows와 유사하게 Queryx가 반환됩니다.

  • sqlx.Row - sql.Row와 유사하게 QueryRowx가 반환됩니다.

database/sql 방식과 비교하여 새로운 구문을 가지고 있어 얻은 데이터를 바로 구조로 변환할 수 있습니다.

  • Get(dest 인터페이스{}, …) error

  • Select(dest 인터페이스{}, …) error

테이블 만들기

다음 예제는 모두 다음과 같은 테이블 구조를 갖습니다. 운영의 기초.

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는

Exec 및 MustExec를 사용하여 연결 풀에서 연결을 가져온 다음 해당 쿼리 작업을 실행합니다. 임시 쿼리 실행을 지원하지 않는 드라이버의 경우 작업 실행 뒤에 준비된 문이 생성됩니다. 이 연결은 결과가 반환되기 전에 연결 풀로 반환됩니다.

다른 데이터베이스 유형은 다른 자리 표시자를 사용한다는 점에 유의해야 합니다. mysql은 무엇을 사용합니까? 자리 표시자 기호로 사용됩니다.

  • MySQL을 사용하셨나요?

  • PostgreSQL은 1,1,2 등을 사용합니다.

  • SQLite는 사용합니까? 또는 $1

  • Oracle 사용: name

Exec를 사용하여 이 예제를 추가하거나 삭제합니다.

Query를 사용한 쿼리 구문은 나중에 언급할 예정입니다.

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 준비된 문

대부분의 데이터베이스에서 쿼리가 실행될 때 , SQL 문 데이터베이스 내부에 해당 문이 선언되어 있습니다. 해당 문은 다른 곳에서 재사용할 수 있도록 미리 선언할 수 있습니다.

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)

물론 sqlx는 확장을 위한 preparex()도 제공하는데, 이는 구조 변환에 직접 사용할 수 있습니다.

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

Query

행 결과는 데이터베이스/SQL의 Rows를 사용하여 얻습니다. 쿼리는 sql.Rows 개체와 오류 개체를 반환합니다.

사용 시 일련의 결과 대신 행을 커서로 처리해야 합니다. 데이터베이스 드라이버 캐싱 방법은 다르지만 Next() 반복을 통해 매번 하나의 결과를 얻습니다. 쿼리 결과가 매우 큰 경우 Scan()을 사용하여 각 열을 매핑하는 데 메모리 사용량을 효과적으로 제한할 수 있습니다. 문자열, []바이트 등과 같은 언어 데이터 유형이 사용됩니다. 모든 행 결과를 반복하지 않는 경우 연결 풀에 연결을 반환하기 전에 Row.Close()를 호출해야 합니다.

Query에서 반환되는 오류는 서버에서 쿼리를 준비하는 중에 발생할 수도 있고, 쿼리문을 실행할 때 발생할 수도 있습니다. 예를 들어, 데이터베이스가 사용 가능한 연결을 찾거나 생성하기 위해 10번을 시도하더라도 연결 풀에서 잘못된 연결을 가져올 수 있습니다. 일반적으로 오류는 주로 SQL 문의 오류, 유사한 일치 오류, 도메인 이름이나 테이블 이름의 오류로 인해 발생합니다.

대부분의 경우 Rows.Scan()은 드라이버가 캐시를 사용하는 방식에 관계없이 드라이버에서 얻은 데이터의 복사본을 만듭니다. 특수 유형 sql.RawBytes를 사용하여 드라이버가 반환한 데이터에서 제로 복사본 슬라이스 바이트를 얻을 수 있습니다. 다음에 Next가 호출되면 드라이버가 가리키는 메모리를 다른 데이터로 덮어썼기 때문에 값이 유효하지 않게 됩니다.

Query에서 사용하는 연결은 Next()를 통해 모든 행을 순회한 후 또는rows.Close()가 호출된 후 해제됩니다.

예:

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는 Query와 매우 유사하게 동작하지만 sqlx.Rows 개체를 반환하고 확장된 스캔 동작을 지원하며 데이터에 대한 구조 변환을 수행할 수 있습니다.

예:

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

QueryRow 및 QueryRowx는 모두 데이터베이스에서 데이터 조각을 가져오지만 QueryRowx는 결과를 구조로 직접 변환할 수 있는 스캔 확장을 제공합니다.

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(매우 일반적으로 사용됨)

Get and Select는 결과를 구조에 직접 할당할 수 있고 변환을 위해 StructScan을 내부적으로 캡슐화하는 매우 시간을 절약해 주는 확장입니다. Get 메서드를 사용하여 단일 결과를 얻은 다음 Scan 메서드를 사용하고 Select 메서드를 사용하여 결과 조각을 얻습니다.

예:

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

트랜잭션 작업은 세 가지 방법을 통해 구현됩니다.

Begin(): 트랜잭션 열기

Commit(): 트랜잭션 커밋(sql 실행)

Rollback(): 롤백

사용 과정:

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

위 내용은 mysql 데이터베이스에 golang을 연결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제