首页 > 数据库 >Go--连接mysql,增删改查

Go--连接mysql,增删改查

时间:2023-12-05 11:26:51浏览次数:84  
标签:name err -- fmt 改查 mysql Println 连接 连接池

下载驱动库,下为官方推荐的,还有其他ORM库,暂时没涉及,故本文不做阐述

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

 

一、连接

1.1 直接连接,查询单行

package main

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

func OneLineQuery() {
    //拼接mysql数据库信息
    dataSourceName := user + ":" + password + "@tcp(" + host + ":" + port + ")/" + database + "?charset=utf8&parseTime=True"
    //连接mysql
    conn, err := sql.Open("mysql", dataSourceName)
    if err != nil {
        fmt.Println("Failed to connect to database", err)
        return
    }
    //记得结束后关闭连接
    defer conn.Close()

    //单行查询,不管语句查询多久的数据,只返回最新一行数据
    row := conn.QueryRow("select psa_id,name from table_name;")
    //提取数据
    var psaId int //根据表结构定义变量类型,建议与列名一致
    var name string
    err = row.Scan(&psaId, &name) //根据查询条件与表结构,修改对应的列名,顺序要一一对应
    if err != nil {
        fmt.Println("Failure to interpolate data", err)
    }
    fmt.Println(psaId, name) //输出查询数据
}

func main() {
    OneLineQuery()
}

 

1.2 使用连接池

1.2.1 连接池

通过内存中维护一组数据库连接,以便在需要时快速分配和释放连接。

连接池可以有效地管理和复用数据库连接,避免频繁的打开和关闭数据库连接,提高性能并减少资源浪费,故它是以长链接的形式存在内存中。

1.2.2 创建调用

用sql.Open函数创建连接池,可是此时只是初始化了连接池,并没有创建任何连接。连接创建都是惰性的,只有当你真正使用到连接的时候,连接池才会创建连接。

函数调用:

  • db.Ping() :调用完毕后会马上把连接返回给连接池。通常使用db.Ping()方法初始化,调用了Ping之后,连接池一定会初始化一个数据库连接
  • db.Exec() :调用完毕后会马上把连接返回给连接池,但是它返回的Result对象还保留着连接的引用,当后面的代码需要处理结果集的时候连接将会被重用。
  • db.Query() :调用完毕后会将连接传递给sql.Rows类型,当然后者迭代完毕或者显示的调用.Clonse()方法后,连接将会被释放回到连接池。
  • db.QueryRow():调用完毕后会将连接传递给sql.Row类型,当.Scan()方法调用之后把连接释放回到连接池。
  • db.Begin() :调用完毕后将连接传递给sql.Tx类型对象,当.Commit()或.Rollback()方法调用后释放连接。
1.2.3 连接失败

若连接失败,database/sql会自动尝试重连10次,仍然无法重连的情况下会自动从连接池再获取一个或者新建另外一个。

1.2.4 相关配置

先了解下mysql的相关配置

字段 简述 说明
max_connections 同时处理的最大连接数 通常默认是200,如果服务器达到了这个限制,新的连接请求将被拒绝,直到当前连接数小于阈值为此,可根据业务需求、服务性能进行修改
extra_max_connections 超过最大连接数后最多可接受的连接数 指定了服务器可同时处理的最大连接数。如果服务去繁忙,且连接数已达到了max_connections的限制,这个配置允许服务器接收更多的请求,但可能影响性能,非必要不使用
wait_timeout 非交互式连接(程序之间调用,如一边是tomcat web服务器,一边是数据库服务器)最大空闲时间 如果一段时间内,连接没有发送任何请求,则mysql会断开这个连接,通常默认是8小时(28800秒)
interactive_timeout 交互式连接(本地打开mysql的客户端,在黑窗口下进行各种sql操作)最大空闲时间 默认也是8小时(28800秒)

查看及修改

#查询
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'interactive_timeout';

#修改,对已经存在的连接不生效,重新建立连接后生效
SET GLOBAL max_connections = 200;
SET GLOBAL wait_timeout=120;
SET GLOBAL interactive_timeout=120;

#永久修改
#修改mysql配置文件(通常是my.cnf或my.ini),重启MySQL服务生效
[mysqld]
max_connections = 200
wait_timeout=28800
interactive_timeout=28800

go连接池相关配置:

  • SetMaxOpenConns:最大打开连接数,默认为0,不限制,应小于数据库max_connections的值
  • SetMaxIdleConns:最大空闲连接数,应小于SetMaxOpenConns的值
  • SetConnMaxLifetime:连接的最大生命周期,默认为0不限制。指定了从建立连接开始到连接关闭之间的总时间(活动+空闲时间),应小于数据库本身的连接超时时间
  • SetConnMaxIdleTime:连接的最大空闲时间,指定了连接在没有任何数据传输活动时的最长闲置时间。如果超过这个时间,连接将被关闭

示例:

// DB 设置全局变量
var DB *sql.DB

// ConnectionPool 连接池配置
func ConnectionPool() {
    //拼接mysql数据库信息
    dataSourceName := user + ":" + password + "@tcp(" + host + ":" + port + ")/" + database + "?charset=utf8&parseTime=True"
    //连接mysql
    db, err := sql.Open("mysql", dataSourceName)
    if err != nil {
        fmt.Println("Failed to connect to database", err)
        return
    }
    //连接池配置
    db.SetMaxOpenConns(100)                 //最大打开连接数,0为不限制
    db.SetMaxIdleConns(10)                  //最大闲置连接数
    db.SetConnMaxIdleTime(time.Second * 10) //最大空闲时间
    //db.SetConnMaxLifetime(time.Minute * 30) //连接超时时间,应小于数据库本身的连接超时时间
    //defer db.Close()    //后面代码引用,这里暂不关闭
    //赋值
    DB = db
}

 

二、增删改查

以下的操作都使用1.2中的DB变量

2.1 查询

单行查询如1.1,下为多行查询

在遍历时一行行的输出查询数据,在函数中引用

func MultilineQuery() {
    rows, err := DB.Query("select psa_id,name from table_name limit 5;")
    if err != nil {
        fmt.Println("Inquiry Failure", err)
    }
    defer rows.Close()
    //遍历查询结果
    for rows.Next() {
        var psaId int
        var name string
        err = rows.Scan(&psaId, &name) //将查询结果映射到变量中
        if err != nil {
            fmt.Println("Scan data mapping failure", err)
        }
        //输出数据
        fmt.Printf("ID: %d, Name: %s\n", psaId, name)
    }

    //程序调用完毕后关闭连接池
    defer DB.Close()
}

先定义一个结构体,将查询结果映射进结构体内,作为函数返回值,这样查询结构可在查询函数外引用

// 定义结构体,结构类型跟查询字段类型一致,注意顺序
type str struct {
    psaId int
    name  string
}

func MultilineQuery() []str {
    rows, err := DB.Query("select psa_id,name from table_name limit 5;")
    if err != nil {
        fmt.Println("Inquiry Failure", err)
    }
    defer rows.Close()

    var str1 []str //定义结构体切片,作为函数返回值
    //遍历查询结果
    for rows.Next() {
        var str2 str                             //定义结构体变量
        err = rows.Scan(&str2.psaId, &str2.name) //将查询数据映射到变量中,按顺序
        if err != nil {
            fmt.Println("Scan data mapping failure", err)
        }
        str1 = append(str1, str2) //将查询数据添加至结构体切片末尾
    }

    //程序调用完毕后关闭连接池
    defer DB.Close()

    //返回值
    return str1
}

// ExportData 引用str1
func ExportData(str1 []str) {
    //遍历
    for _, v := range str1 {
        //输出数据
        fmt.Println(v.psaId, v.name)
        fmt.Println(v)
    }
}

func main() {
    //OneLineQuery()
    ConnectionPool()
    str1 := MultilineQuery()
    ExportData(str1)
}

 

2.2 增删改

插入数据

func InsertData() {
    // 插入数据的SQL语句
    //与表结构一致,不然可能会报错,自增主键字段可忽略不写,将自动生成
    //但clickhouse的自增主键不可忽略,可用"INSERT INTO table_name (id, column2) VALUES (generateUUIDv4(), ?)"表示
    sqlStatement := "INSERT INTO table_name (column1, column2) VALUES (?, ?)"

    // 创建事务
    tx, err := DB.Begin()
    if err != nil {
        fmt.Println("事务创建失败:", err)
        return
    }

    // 执行插入语句
    _, err = tx.Exec(sqlStatement, "value1", "value2") //value输入具体的值
    if err != nil {
        fmt.Println("插入数据失败:", err)
        tx.Rollback() // 回滚事务
        return
    }

    // 提交事务
    err = tx.Commit()
    if err != nil {
        fmt.Println("提交事务失败:", err)
        return
    }

    fmt.Println("数据插入成功!")
}

删除数据

// 执行删除操作
    _, err = DB.Exec("DELETE FROM table_name WHERE condition")
    if err != nil {
        // 处理删除失败的情况
    }

更改数据

    // 执行更新语句
    err = DB.QueryRow("UPDATE table_name SET column1 = ? WHERE id = ?", "new_value", 1).Scan()
    if err != nil {
        fmt.Println("更新数据失败:", err)
        return
    }

 

标签:name,err,--,fmt,改查,mysql,Println,连接,连接池
From: https://www.cnblogs.com/Xinenhui/p/17874922.html

相关文章

  • Ansible自动化运维模块详解
    ansible ad-hoc点对点模块l ping模块主机连通性测试[root@node2~]#ansibleall-mping192.168.200.10|SUCCESS=>{    "ansible_facts":{        "discovered_interpreter_python":"/usr/bin/python"    },    "changed":fals......
  • CSS按钮样式之button标签与input type=button的区别
    原文链接:1、https://www.cnblogs.com/weihanli/p/5162828.html         2、https://www.cnblogs.com/smile6542/p/11968175.html   如果想要在页面上表示一个显示文本的按钮推荐input[type=”button”]方式,如果想要呈现一个图片内容或内容更丰富的按钮推......
  • ChatGPT 同类工具推荐
    原文:https://openaigptguide.com/chatgpt-similar%20software/ChatGPT是一款由美国OpenAI公司开发的人工智能语言模型,类似的软件有:火山写作(VolcanoWriting):它是一款用户友好的写作软件,可以自动生成具有创造性和连贯性的文本。这款软件的功能丰富,支持快速生成文章、段落、句......
  • openssh版本升级
    1.准备opensshrpm包opensshrpm包打包方法见另一篇博客  2.备份openssh配置mkdir/etc/sshconfig_backupcp/etc/ssh/sshd_config/etc/sshconfig_backup/cp/etc/pam.d/sshd/etc/sshconfig_backup/pam.d_sshd3.升级opensshrpm-Uvhopenssh*.rpm4.还原ssh配置......
  • linux基础命令--文件管理类
    1.cat命令简介:打印文件到屏幕上格式cat[-AbeEnstTuv][--help][--version]fileName参数说明:-n或--number:由1开始对所有输出的行数编号。-b或--number-nonblank:和-n相似,只不过对于空白行不编号。-s或--squeeze-blank:当遇到有连续两行以上的空白行,就代换为一......
  • 使用Slurm集群进行分布式图计算:对Github网络影响力的系统分析
    本文分享自华为云社区《基于Slurm集群的分布式图计算应用实践:Github协作网络影响力分析》,作者:yd_263841138。1.引言Slurm(SimpleLinuxUtilityforResourceManagement)是一个针对小型Linux集群的开源、容错、高可扩展的集群管理及作业调度系统,它具备统一管理集群内的计算资源......
  • 2023-13-03-好像又是很emo的一天
    早上起床起得比较晚,因为之前的旅途比较的累然后一天好像也没干什么。。。。。也就整理了一下之前的笔记晚上的时候,去了一下实验室,因为要开周末的分享会我是7:00左右去的,,然后就坐在位置上学习,,并等待周会二点开始但是我想说的是,,,在位置上学习,,突然变得不知道学什么了变得手足无措......
  • 【小测试】玩一玩 VictoriaMetrics 的 force merge
    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!cnblogs博客zhihuGithub公众号:一本正经的瞎扯我是期望通过备份来建立VictoriaMetrics的历史节点,然后历史节点通过forcemerge,让磁盘空间更小,压缩率更高,查询更快。启动历史节点后,我在vm-storage的http端口......
  • Nim 概念 Concept 对性能的影响
    Nim概念Concept对性能的影响继上一篇文章《C#泛型编译特性对性能的影响》后,我又研究了Nim语言相关的设计,由于Nim语言与C#语言有些差异,比如Nim没有接口,也没有直接的class关键字,所以某些实现是变通的办法。概念Concept在Nim中没有Interface的概念,虽然有多次提案,......
  • vue 配合后端请求异步加载APP.vue
    主要是想在加载路由什么的之前先请求一些配置参数,毕竟我的情况是首页要根据不同的配置显示不同的路由组件一般加载App.vue是这么写的import{createApp}from'vue'importAppfrom'./App.vue'createApp(App).mount('#app')异步加载的话,天才我深思熟虑后是这么写的。我......