Go语言对于MySQL的基本操作

news2025/3/19 23:32:07

一.下载依赖

终端中输入:

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

导入包

import (
	"database/sql"

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

二.案例

package main

//go get-u github.com/go-sql-driver/mysql  获取驱动
import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

var db *sql.DB
//根据数据库表中,有属性id,name,age,且id为插入时,自增1
var usergroup map[int]user = make(map[int]user, 100)

type user struct {
	id   int
	name string
	age  int
}

func initDB() (err error) {
	//连接数据库  user:password@tcp(ip:port)/databasename
	dsn := "root:123456@tcp(127.0.0.1:3306)/sql_test"
	db, err = sql.Open("mysql", dsn) //dsn格式不对这里会报错
	if err != nil {
		fmt.Printf("dsn: %s invaid! err:%v\n", dsn, err)
		return err
	}

	//判断一下是否连接成功
	err = db.Ping()
	if err != nil {
		fmt.Printf("open %s failed! err:%v\n", dsn, err)
		return err
	} else {
		fmt.Printf("open %s success!\n", dsn)
	}
	//设置数据库连接池的最大连接数,根据业务调整
	db.SetMaxOpenConns(10)
	db.SetMaxIdleConns(5) //最大闲置连接数
	return nil
}

// 输入id,返回对应的user信息  查询单条记录
func queryOne(id int) (u user, err error) {
	//查询单条语句
	sqlstr := "select * from user where id=?" //?为占位符,在Query的时候可以用后续的参数进行填充
	rowObj := db.QueryRow(sqlstr, id)         //从数据库连接池中拿去一个连接去进行查询
	//得到了rowObj必须调用Scan方法,因为该方法会释放数据库连接,把连接放回连接池,否则连接池最大连接用完,则会影响后续连接查询
	rowObj.Scan(&u.id, &u.name, &u.age)
	if rowObj == nil {
		fmt.Printf("query failed,err:%v\n", err)
		return u, err
	}
	return u, nil
}

// 查询多行  读取到map中
func query() (err error) {
	sqlstr := "select * from user"
	rows, err := db.Query(sqlstr)
	if err != nil {
		fmt.Printf("query failed,err:%v\n", err)
		return
	}
	//记得关闭,放回连接池
	defer rows.Close()
	var u user
    //用一个for循环,把每次读到的行信息,存放到全局变量usergroup中,达到程序启动初始化的效果
	for rows.Next() {
		err = rows.Scan(&u.id, &u.name, &u.age)
		if err != nil {
			fmt.Printf("scan failed,err:%v\n", err)
			return
		}
		usergroup[u.id] = u
	}
	return nil
}

// 插入一条学生数据,并且更新map  id是主码,
//实际插入学生数据的时候,并不知道数据库中学号应该分配多少,所以在插入后得到返回的id,再更新map
func insert(u user) (id int64, err error) {
	sqlstr := "insert into user(name,age) values(?,?)"
	var res sql.Result
    //执行该语句
	res, err = db.Exec(sqlstr, u.name, u.age)
	if err != nil {
		fmt.Printf("insert failed,err:%v\n", err)
		return
	}
	//拿到插入的id,返回
	id, err = res.LastInsertId()
	if err != nil {
		fmt.Printf("insert failed,err:%v\n", err)
		return
	}
	return id, nil
}

//删除指定id的user,实际上最好判断一下是否存在map中,这里就先不写了
func deleteUser(id int) (err error) {
	sqlstr := "delete from user where id=?"
	_, err = db.Exec(sqlstr, id)
	if err != nil {
		fmt.Printf("delete failed,err:%v\n", err)
		return err
	}
	delete(usergroup, id)
	return nil
}

// 查询单条语句
func test01() {
	//查询学号为1的学生信息
	u, err := queryOne(1)
	if err != nil {
		fmt.Printf("query failed,err:%v\n", err)
		return
	}
	println(u.id, u.name, u.age)

}

// 程序初始化时,把user表中信息全部读取到map中
func readToMap() {
	//从数据库中读取user放入map中
	err := query()
	if err != nil {
		fmt.Printf("query failed,err:%v\n", err)
		return
	}
}

// 测试插入
func myInsertTest() {
	var u user
	u.age = 23
	u.name = "周杰伦"
	id, err1 := insert(u)
	if err1 != nil {
		fmt.Printf("insert failed,err:%v\n", err1)
		return
	}
	//说明插入成功
	u.id = int(id)
	usergroup[u.id] = u
}

//遍历map
func printMap() {
	//遍历
	for _, u := range usergroup {
		println(u.id, u.name, u.age)
	}
	println("***************************************")
}

func main() {
	err := initDB()
	defer db.Close()
	if err != nil {
		fmt.Printf("init db failed,err:%v\n", err)
		return
	}
	readToMap()
	printMap()

	myInsertTest()
	printMap()

}

三.预处理

预处理执行过程:

  1. 把SQL语句分成两部分,命令部分与数据部分。
  2. 先把命令部分发送给MySQL服务端,MySQL服务端进行SQL预处理。
  3. 然后把数据部分发送给MySQL服务端,MySQL服务端对SQL语句进行占位符替换。
  4. MySQL服务端执行完整的SQL语句并将结果返回给客户端。

优点:

  1. 优化MySQL服务器重复执行SQL的方法,可以提升服务器性能,提前让服务器编译,一次编译多次执行,节省后续编译的成本。
  2. 避免SQL注入问题。
func prepareInsert() {
	sqlstr := "insert into user(name,age) values(?,?)"
	//先将sql语句发送给数据库,为后续执行做准备,后续只需要传递参数即可
	stmt, err := db.Prepare(sqlstr)
	if err != nil {
		fmt.Printf("prepare failed,err:%v\n", err)
		return
	}
	defer stmt.Close()
	//后续只需要用stmt执行操作,传递参数
	res, err1 := stmt.Exec("陶喆", 18)
	if err1 != nil {
		fmt.Printf("insert failed,err:%v\n", err1)
		return
	}
	id, err2 := res.LastInsertId()
	if err2 != nil {
		fmt.Printf("insert failed,err:%v\n", err2)
		return
	}
	usergroup[int(id)] = user{int(id), "陶喆", 18}

}

四.事务操作

//事务操作
func transactionDemo() {
	//开启事务
	tx,err:=db.Begin()
	if err!=nil{
		fmt.Printf("begin failed,err:%v\n", err)
		return
	}
	//执行多个SQL操作
	sqlstr1:="update user set age=? where id=1"
	sqlstr2:="update user set age=? where id=2"

	_,err=tx.Exec(sqlstr1, 18)
	if err!=nil{
		//回滚
		fmt.Println("sqlstr1 failed,err:%v\n", err)
		tx.Rollback()
	}
	_,err=tx.Exec(sqlstr2, 18)
	if err!=nil{
		fmt.Println("sqlstr2 failed,err:%v\n", err)
		//回滚
		tx.Rollback()
	}
	//提交
	tx.Commit()
}

五.对于sqlx库的使用

下载依赖:

go get github.com/jmoiron/sqlx

package main

import (
	"fmt"

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

var db *sqlx.DB

//和上一个例子不一样,这个要字段要供其它包方法使用,比如Get方法需要对结构体进行反射,所以要大写
type user struct {
	Id   int
	Name string
	Age  int
}

func initDB() (err error) {
	dsn := "root:9826942694yzy@tcp(127.0.0.1:3306)/sql_test"
	// 也可以使用MustConnect连接不成功就panic
	db, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		fmt.Printf("connect DB failed, err:%v\n", err)
		return
	}
	//这是最大连接池数量和最大休闲连接池数量
	db.SetMaxOpenConns(20)
	db.SetMaxIdleConns(10)
	return
}

func main() {
	err := initDB()
	if err != nil {
		fmt.Printf("init db failed,err:%v\n", err)
		return
	}
	defer db.Close()

	sqlStr := "select *from user where id=?"
	var u user
	err = db.Get(&u, sqlStr, 1)
	if err != nil {
		fmt.Printf("get failed, err:%v\n", err)
		return
	}
	fmt.Println(u.Id, u.Name, u.Age)

	var userlist = make([]user, 100)
	sqlStr1 := "select * from user"
	err = db.Select(&userlist, sqlStr1)
	if err != nil {
		fmt.Printf("select failed,err:%v\n", err)
		return
	}
	fmt.Println(userlist)
}

六.sql注入问题

func main() {
	err := initDB()
	if err != nil {
		fmt.Printf("init db failed,err:%v\n", err)
		return
	}
	defer db.Close()
	//这样符合要求
	inject_demo("周杰伦")
	//但是由于用户可以自行输出,如果输入以下,会输出所有
	//"select * from user where name='xxx' or 1=1#'"  == select * from user where name='xxx' or 1=1  这样会输出所有信息 #在mysql中是注释
	inject_demo("xxx' or 1=1#")
	//select *from user where name='xxx' union select * from user  输出所有
	inject_demo("xxx' union select * from user#")
	
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2318029.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AndroidStudio下载安装,环境部署以及常见问题解决教程(亲测)

AndroidStudio下载安装,环境部署以及常见问题解决!!! 文章目录 前言 一、Android Studio 下载与安装 1.1 系统要求 1.2 下载 Android Studio 1.3 安装 Android Studio Windows 系统 1.4 初始配置 二、环境部署 2.1 安装 …

开源免费一句话生成儿童故事视频核心思想解析

再看一个演示视频,学会核心思想后,可以打造自己的内容生成工具,后文有基于飞书多维表格的实现效果: 一句话灵感生成儿童故事视频演示 这是一款专门为内容素材创作打造的创新工具,可根据用户输入的主题,快速…

数据结构——最短路(BFS,Dijkstra,Floyd)

完整版可以看我的最短路问题模版总结_稠密图最短路-CSDN博客 考研数据结构只考BFS,Dijkstra和Floyd 下面代码以Acwing模板题为例 BFS代码 适用类型&#xff1a; 1.单源最短路径 2.无权图 3.不适用于带权图和负权回路图 //Acwing走迷宫bfs #include<bits/stdc.h>usi…

Kali Linux汉化教程:轻松设置中文界面

1.打开终端 2.输入sudo dpkg-reconfigure locales&#xff0c;回车&#xff0c;输入密码&#xff0c;回车 sudo dpkg-reconfigure locales 3.往下滑&#xff0c;滑到底&#xff0c;找到‘zh_CN.UTF-8 UTF-8’,回车 4.选择‘zh_CN.UTF-8’,回车 5.没有 ‘zh_CN.UTF-8’选项的特…

C++和标准库速成(八)——指针、动态数组、const、constexpr和consteval

目录 1. 指针和动态数组1.1 栈和自由存储区1.2 使用指针1.3 动态分配的数组1.4 空指针常量 2. const2.1 const修饰类型2.2 const与指针2.3 使用const保护参数2.4 const方法(建议&#xff09; 3. constexpr4. consteval参考 1. 指针和动态数组 动态内存允许所创建的程序具有在编…

超声重建,3D重建 超声三维重建,三维可视化平台 UR 3D Reconstruction

1. 超声波3D重建技术的实现方法与算法 技术概述 3D超声重建是一种基于2D超声图像生成3D体积数据的技术&#xff0c;广泛应用于医学影像领域。通过重建和可视化三维结构&#xff0c;3D超声能够显著提高诊断精度和效率&#xff0c;同时减少医生的脑力负担。本技术文档将详细阐述…

[HelloCTF]PHPinclude-labs超详细WP-Level 6Level 7Level 8Level 9-php://协议

由于Level 6-9 关的原理都是通用的, 这里就拿第6关举例, 其他的关卡同理 源码分析 定位到代码 isset($_GET[wrappers]) ? include("php://".$_GET[wrappers]) : ; 与前几关发生变化的就是 php:// 解题分析 这一关要求我们使用 php协议 php:// 协议 php://filte…

【Linux】Bash是什么?怎么使用?

李升伟 整理 什么是 Bash&#xff1f; Bash&#xff08;Bourne Again Shell&#xff09;是一种 命令行解释器&#xff08;Shell&#xff09;&#xff0c;广泛用于 Unix 和 Linux 操作系统。它是 Bourne Shell&#xff08;sh&#xff09; 的增强版&#xff0c;提供了更多的功能…

如何创建并保存HTML文件?零基础入门教程

原文&#xff1a;如何创建并保存HTML文件&#xff1f;零基础入门教程 | w3cschool笔记 本文将以Windows系统为例&#xff0c;教你用最简单的记事本创建并保存第一个HTML网页。 &#x1f4dd; 第一步&#xff1a;准备工具 文本编辑器&#xff1a;使用系统自带的记事本&#xff…

React19源码系列之FiberRoot节点和Fiber节点

在上一篇文章&#xff0c;看了createRoot函数的大致流程。 createContainer函数创建并返回了FiberRoot 。FiberRoot是由createFiberRoot函数创建&#xff0c; createFiberRoot函数还将 FiberRoot和 根Fiber 通过current属性建立起了联系。将FiberRoot作为参数传给 ReactDOMRoo…

TCP协议的多线程应用、多线程下的网络编程

DAY13.2 Java核心基础 多线程下的网络编程 基于单点连接的方式&#xff0c;一个服务端对应一个客户端&#xff0c;实际运行环境中是一个服务端需要对应多个客户端 创建ServerSocketNable类&#xff0c;多线程接收socket对象 public class ServerSocketNable implements Run…

华为中小型企业项目案例

实验目的(1) 熟悉华为交换机和路由器的应用场景 (2) 掌握华为交换机和路由器的配置方法 实验拓扑实验拓扑如图所示。 华为中小型企业项目案例拓扑图 实验配置市场部和技术部的配置创建VLANLSW1的配置 [LSW1]vlan batch 10 20 [LSW1]q…

LabVIEW VI Scripting随机数波形图自动生成

通过LabVIEW VI Scripting 技术&#xff0c;实现从零开始编程化创建并运行一个随机数波形监测VI。核心功能包括自动化生成VI框架、添加控件与函数、配置数据流逻辑及界面布局优化&#xff0c;适用于批量生成测试工具、教学模板开发或复杂系统的模块化构建。通过脚本化操作&…

MATLAB 控制系统设计与仿真 - 26

状态空间控制系统概述 状态空间描述 现代控制理论是建立在状态空间基础上的控制系统分析和设计理论&#xff0c;它用状态变量来刻画系统的内部特征&#xff0c;用‘一节微分方程组’来描述系统的动态特性。系统的状态空间模型描述了系统输入/输出与内部状态之间的关系&#x…

Python----计算机视觉处理(Opencv:图像镜像旋转)

一、图像镜像旋转 图像的旋转是围绕一个特定点进行的&#xff0c;而图像的镜像旋转则是围绕坐标轴进行的。图像镜像旋转&#xff0c;也可 以叫做图像翻转&#xff0c;分为水平翻转、垂直翻转、水平垂直翻转三种。 通俗的理解为&#xff0c;当以图片的中垂线为x轴和y轴时&#x…

C++从入门到入土(八)——多态的原理

目录 前言 多态的原理 动态绑定与静态绑定 虚函数表 小结 前言 在前面的文章中&#xff0c;我们介绍了C三大特性之一的多态&#xff0c;我们主要介绍了多态的构成条件&#xff0c;但是对于多态的原理我们探讨的是不够深入的&#xff0c;下面这这一篇文章&#xff0c;我们将…

PyCharm安装redis,python安装redis,PyCharm使用失败问题

报错信息 Usage: D:\wb2\wbrj_pys\venv\Scripts\python.exe -m pip install [options] [package-index-options] … D:\wb2\wbrj_pys\venv\Scripts\python.exe -m pip install [options] -r [package-index-options] … D:\wb2\wbrj_pys\venv\Scripts\python.exe -m pip instal…

保姆级离线TiDB V8+解释

以前学习的时候还是3版本&#xff0c;如今已经是8版本了 https://cn.pingcap.com/product-community/?_gl1ujh2l9_gcl_auMTI3MTI3NTM3NC4xNzM5MjU3ODE2_gaMTYwNzE2NTI4OC4xNzMzOTA1MjUz_ga_3JVXJ41175MTc0MTk1NTc1OC4xMS4xLjE3NDE5NTU3NjIuNTYuMC41NDk4MTMxNTM._ga_CPG2VW1Y4…

PyTorch 深度学习实战(17):Asynchronous Advantage Actor-Critic (A3C) 算法与并行训练

在上一篇文章中&#xff0c;我们深入探讨了 Soft Actor-Critic (SAC) 算法及其在平衡探索与利用方面的优势。本文将介绍强化学习领域的重要里程碑——Asynchronous Advantage Actor-Critic (A3C) 算法&#xff0c;并展示如何利用 PyTorch 实现并行化训练来加速学习过程。 一、A…

Docker换源加速(更换镜像源)详细教程(2025.3最新可用镜像,全网最详细)

文章目录 前言可用镜像源汇总换源方法1-临时换源换源方法2-永久换源&#xff08;推荐&#xff09;常见问题及对应解决方案1.换源后&#xff0c;可以成功pull&#xff0c;但是search会出错 补充1.如何测试镜像源是否可用2.Docker内的Linux换源教程 换源速通版&#xff08;可以直…