Go vscode 操作MySQL NO.1

导入包

        在golang.org中选择packages,搜索mysql

        选择第一个, 根据其中提示进行导入

提示 在shell中输入

$ go get -u github.com/go-sql-driver/mysql

        (需要安装git) 

        若出现以下提示:

PS D:\goLang\mysql> go get -u github.com/go-sql-driver/mysql
go: go.mod file not found in current directory or any parent directory.
        'go get' is no longer supported outside a module.
        To build and install a command, use 'go install' with a version,
        like 'go install example.com/cmd@latest'
        For more information, see https://golang.org/doc/go-get-install-deprecation
        or run 'go help get' or 'go help install'.

        说明go get命令在module之外不再获得支持,需要在当前进行go module 的初始化,来建立相关的go mod文件,命令如下

go mod init 项目名

        此时可以继续进行操作

         出现上面提示,导包成功

获得数据库的连接

        sql.open不会直接建立一个连接,因此不会因为服务器是否可用或者密码、用户名不正确而报错。因此,使用db.ping来验证是否可用

        Open打开一个dirverName指定的数据库,dataSourceName指定数据源,一般至少包括数据库文件名和其它连接必要的信息。

package main

import (
	"database/sql"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

func main() {

	// See "Important settings" section.

//db, err := sql.Open("mysql", "user:password@/dbname")
	db, err := sql.Open("mysql", "root:123456@/itheima")
//根据自己的设置填入用户名和密码,纯测试数据库名可以不填,保留最后的'/'即可

	db.SetConnMaxLifetime(time.Minute * 3)
	db.SetMaxOpenConns(10)
	db.SetMaxIdleConns(10)
	if err != nil {
		panic(err.Error()) // Just for example purpose. You should use proper error handling instead of panic
	}
	defer db.Close()
//-------------------------------------
	// OPEN不会创建数据库连接,使用ping来验证DSN数据:
	err = db.Ping()//-----------------------------
	if err != nil {
		panic(err.Error()) // proper error handling instead of panic in your app
	}

	// Use the DB normally, execute the querys etc
    //...
}

        SetMaxOpenConns设置与数据库建立连接的最大数目。 如果n大于0且小于最大闲置连接数,会将最大闲置连接数减小到匹配最大开启连接数的限制。 如果n<=0,不会限制最大开启连接数,默认为0(无限制)。

        SetMaxIdleConns设置连接池中的最大闲置连接数。 如果n大于最大开启连接数,则新的最大闲置连接数会减小到匹配最大开启连接数的限制。 如果n<=0,不会保留闲置连接。

        我们可以将这部分代码封装为一个函数,方便后续操作。这部分即为DBinit,封装为DBsql包

为了后续使用,需要返回相关数据库接口db

        返回的DB对象可以安全地被多个goroutine并发使用,并且维护其自己的空闲连接池。因此,Open函数应该仅被调用一次,很少需要关闭这个DB对象。

package DBsql

import (
	"database/sql"
	"fmt"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

// 初始化数据库
func DBinit() *sql.DB {

	// See "Important settings" section.

	db, err := sql.Open("mysql", "root:123456@/itheima")
	db.SetConnMaxLifetime(time.Minute * 3)
	db.SetMaxOpenConns(10)
	db.SetMaxIdleConns(10)
	if err != nil {
		panic(err.Error()) // Just for example purpose. You should use proper error handling instead of panic
	}
	defer db.Close()

	// Open doesn't open a connection. Validate DSN data:
	err = db.Ping()
	if err != nil {
		panic(err.Error()) // proper error handling instead of panic in your app

	}
	fmt.Println("连接成功")
return db
	// Use the DB normally, execute the querys etc
}

插入数据

        我们定义一个全局变量db,用来保存数据库连接对象。将上面的示例代码拆分出一个独立的initDB函数,只需要在程序启动时调用一次该函数完成全局变量db的初始化,其他函数中就可以直接使用全局变量db了。

        为了方便后续操作,先在mysql中建立test表

create table test(
    id int primary key auto_increment comment '编号',
    name varchar(3) comment  '姓名',
    age int comment '年龄'
)comment '用户表';

         插入、更新和删除操作都是用Exec方法

func (db *DB) Exec(query string, args ...any) (Result, error)

这里实例如下: 

func main() {

	//初始化连接
	db = DBsql.InitDB()
	//最后 断开连接
	defer db.Close()
//-----------------------------------------------------------------------------
	//第一句为DML语句,其中‘?’为相关参数,在后面进行补充
	ret, err := db.Exec("insert into test (name,age) values (?,?)", "赵云", 22)
//-----------------------------------------------------------------------------
	if err != nil {
		fmt.Println("插入失败")
		fmt.Printf("err: %v\n", err)
	} else {
		fmt.Println("ok!")
	}
	//这里查询新插入数据的ID
	i, err2 := ret.LastInsertId()
	if err2 != nil {
		fmt.Println("get lastInsertID failed")
	}
	fmt.Printf("insert success, ID is: %v\n", i)
}

执行结果如下: 

[Running] go run "c:\Users\wang2\go\mysql\main.go"
连接成功
ok!
insert success, ID is: 1

        可以将其 封装为insert_test函数,第一个参数为姓名,第二个参数为年龄

func main() {

	//初始化连接
	db = DBsql.InitDB()
	//最后 断开连接
	defer db.Close()

	insert_test("王二", 23)

}

func insert_test(name string, age int) {
	//第一句为DML语句,其中‘?’为相关参数,在后面进行补充
	ret, err := db.Exec("insert into test (name,age) values (?,?)", name, age)

	if err != nil {
		fmt.Println("插入失败")
		fmt.Printf("err: %v\n", err)
	} else {
		fmt.Println("ok!")
	}
	//这里查询新插入数据的ID
	i, err2 := ret.LastInsertId()
	if err2 != nil {
		fmt.Println("get lastInsertID failed")
	}
	fmt.Printf("insert success, ID is: %v\n", i)
}

        运行结果:

[Running] go run "c:\Users\wang2\go\mysql\main.go"
连接成功
ok!
insert success, ID is: 2

查询操作

// 定义 表内内容 的结构体,方便后续查询
type test struct {
	ID   int
	name string
	age  int
}

单行查询

        单行查询db.QueryRow()执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。

QueryRow(query string, args ...any) *sql.Row

实例: 

func QueryOneRow() {
	var t test
	//queryrow后调用scan方法进行读取,并且释放数据库连接
	err := db.QueryRow("select * from test where id = ?", 1).Scan(&t.ID, &t.name, &t.age)
	if err != nil {
		fmt.Printf("err: %v\n", err)
	}
	fmt.Printf("t: %v\n", t)
}

查询结果: 

[Running] go run "c:\Users\wang2\go\mysql\main.go"
连接成功
t: {1 赵云 22}

多行查询

        多行查询db.Query()执行一次查询,返回多行结果(即Rows),一般用于执行select命令。参数args表示query中的占位参数。        

func (*sql.DB).Query(query string, args ...any) (*sql.Rows, error)

        这里返回的rows不能直接scan,会提示调用next

[Running] go run "c:\Users\wang2\go\mysql\main.go"
连接成功
err2: sql: Scan called without calling Next

这里实例如下:

func QueryRows() {
	var t test
	r, err := db.Query("select * from test where age > ?", 20)
	if err != nil {
		fmt.Printf("err: %v\n", err)
	}

	for r.Next() {
		err2 := r.Scan(&t.ID, &t.name, &t.age)
		if err2 != nil {
			fmt.Printf("err2: %v\n", err2)
		}
		fmt.Printf("t: %v\n", t)
	}
}

运行结果: 

[Running] go run "c:\Users\wang2\go\mysql\main.go"
连接成功
t: {1 赵云 22}
t: {2 王二 23}

更新数据

如插入数据,更新数据使用Exec方法

func (db *DB) Exec(query string, args ...any) (Result, error)

实例:

func UpdateData() {
	r, err := db.Exec("update test set name = ? where id =?", "王小波", 2)
	if err != nil {
		fmt.Println("数据更新失败,", err)
	}
	//获得影响的行数
	i, _ := r.RowsAffected()
	fmt.Println("更新数据成功,更新行数:", i)
}

结果: 

[Running] go run "c:\Users\wang2\go\mysql\main.go"
连接成功
t: {1 赵云 22}
t: {2 王二 23}
更新数据成功,更新行数: 1

删除数据 

如插入数据,更新数据使用Exec方法

func (db *DB) Exec(query string, args ...any) (Result, error)

 示例:

func DeleteData() {
	r, err := db.Exec("delete from test where id = ?", 1)
	if err != nil {
		fmt.Println("删除成功")
	}
	i, _ := r.RowsAffected()
	fmt.Println("删除行数:", i)
}

结果: 

[Running] go run "c:\Users\wang2\go\mysql\main.go"
连接成功
t: {1 赵云 22}
t: {2 王小波 23}
更新数据成功,更新行数: 0
删除行数: 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值