厦门有没有做网站的/百度seo关键词怎么做
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。
Golang学习专栏:https://blog.csdn.net/qq_35716689/category_12575301.html
前言
对数据库的CURD是现代应用程序的必备功能,Go语言当然也对数据库的操作提供了非常完善的支持。
尽管在Go语言社区中有很多优秀的ORM库或框架(比如GORM,后面也会发文)能让我们更方便地操作数据库,不过要更好地使用ORM库,掌握Go原生操作数据库database/sql包的使用还是有必要的。
所以,在这篇文章中,我们先来学习一下database/sql包的使用吧。
目录
前言
database/sql简介
连接数据库
MySQL
Postgres
SQLite
关闭连接
连接池设置
示例数据表
sql.DB
sql.Stmt
sql.Tx
小结
database/sql简介
我们可以把标准库中的database/sql包看作一个数据库操作抽象层,因为database/sql并不直接连接并操作数据库,而是为不同的数据库驱动提供了统一的API,database/sql包与驱动包(driver)的关系如下图所示:
对数据库的具体操作由对应数据库的驱动包来完成,访问不同的类型的数据库需要导入不同的驱动包,而所有驱动包都必须实现database/sql/driver包下的相关接口,因此database/sql、database/sql/driver以及驱动包的关系如下图所示:
这样做的好处在于,如果某一天我们想迁移数据库,比如从MySQL切换为Postgres,只需要更换驱动包即可,而不需要把数据库操作的代码重写一遍。
连接数据库
连接到数据库,获取一个数据库操作句柄,简单来说可以分为三步:
- 选择对应数据库的驱动,并导入。
- 配置连接数据库所需的DSN。
- 使用sql.Open()函数打开数据连接,获得*sql.DB对象。
DSN是Data Source Name,包含了连接数据库所需的参数,比如用户,密码、数据编码、数据库名称等。
下面我们以MySQL,Postgres,SQLite为例介绍在Go语言中如何连接到数据库。
MySQL
连接MySQL驱动包推荐用github.com/go-sql-driver/mysql库,其完整的DSN为如以所示,可以看到MySQL的DSN各个部分都是可选的:
[username[:password]@][protocol[host[:port]]]/dbname[?param1=value1&...¶mN=valueN]
- username:用户名。
- password:密码,与用户名之间要用冒号分隔。
- protocol:网络协议,默认用tcp即可。
- host:数据库地址。
- port:端口号,默认为3306
- dbname:数据库名称
- param1~paramN:可选参数。
package main import ("database/sql"// 匿名导入_ "github.com/go-sql-driver/mysql"
)func main(){//db为*sql.DB//DSN要根据实际替换db, err := sql.Open("mysql", "user:password@/dbname")if err != nil {panic(err)}
}
Postgres
连接Postgres数据库推荐用github.com/lib/pq,其连接DSN为:
host=192.168.0.1 user=postgres dbname=postgres port=5432 password=123456 sslmode=disable
- user:用户名。
- password:密码,与用户名之间要用冒号分隔。
- dbname:数据库名称。
- sslmode:是否使用ss模式,其值可以是disable,required,verify-ca ,verify-full等。
- host:主机
- port:端口号
package main import ("context""fmt""os""github.com/lib/pq"
)func main(){dsn := "user=postgres dbname=postgres password=123456 sslmode=disable"db, err := sql.Open("postgres", dsn)if err != nil {log.Fatal(err)}defer db.Close()
}
SQLite
连接SQLite数据库推荐用github.com/mattn/go-sqlite3,SQLite是嵌入式数据库,因此它的DSN是数据库文件所在的路径:
import ("database/sql"_ "github.com/mattn/go-sqlite3"
)func main(){dsn := "./test.db"db,err := sql.Open("sqlite3",dsn)
}
关闭连接
打开数据库连接要记得关闭数据连接,一般在defer语句后面调用sql.DB的Close()方法:
import ("database/sql"_ "github.com/mattn/go-sqlite3"
)func main(){dsn := "./test.db"db,err := sql.Open("sqlite3",dsn)if err != nil{panic(err)}//关闭数据库连接defer db.Close()
}
连接池设置
sql.DB对象内包含一个数据库连池,并支持通过以下几个方法设置连接池的相关配置:
db.SetConnMaxLifetime(0) //最大打开的连接时间db.SetMaxIdleConns(50) //最大闲置连接数db.SetMaxOpenConns(50) //最大打开的连接数
示例数据表
为了后面更好的进行实例演示,我们需要一个演示数据库,这里以Mysql数据库为例,数据库名称为test,创建一个users数据表:
CREATE DATABASE IF NOT EXISTS test;USE test;CREATE TABLE IF NOT EXISTS users(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
gender TINYINT NOT NULL DEFAULT 0,
mobile VARCHAR(255) NOT NULL DEFAULT ''
);
sql.DB
前面我们调用sql.Open()获得了sql.DB对象,这是操作数据的句柄,也可以理解为一个数据库连接池,可以通过sql.DB的Conn()可以获得数据库连接池里的单个连接对象sql.Conn:
ctx, _ := context.WithCancel(context.Background())
conn, err := db.Conn(ctx)
无论是sql.DB,还是sql.Conn,其对数据库执行CURD操作的方法是类似,一般推荐使用sql.DB。
执行insert、update、delete用Exec()和ExecContext()方法,其签名如下:
func (db *DB) Exec(query string, args ...any) (Result, error)
func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (Result, error)
上面的方法执行后返回sql.Result接口的实例,这个接口只有两个方法:
type Result interface {//执行insert语句时,返回自增idLastInsertId() (int64, error)//影响行数RowsAffected() (int64, error)
}
示例代码:
package mainimport ("database/sql""fmt"_ "github.com/mattn/go-sqlite3"
)func main() {db, err := sql.Open("sqlite3", "../test.db")if err != nil {panic(err)}defer db.Close()insertSql := "INSERT INTO users(name,gender,mobile) VALUES(?,?,?),(?,?,?)"insertResult, err := db.Exec(insertSql, "小白", 2, "166xxxxxxxx", "小张", 1, "13493023333")if err != nil {panic(err)}lastInsertId, _ := insertResult.LastInsertId()fmt.Printf("最新记录id:%d\n", lastInsertId)rowsAffected, _ := insertResult.RowsAffected()fmt.Println("影响行数:", rowsAffected)updateSql := "UPDATE users SET mobile = ? WHERE id = ?"updateResult, err := db.Exec(updateSql, "136xxxxxxxx", 1)if err != nil {panic(err)}rowsAffected, _ = updateResult.RowsAffected()fmt.Printf("影响行数:%d\n", rowsAffected)deleteSql := "DELETE FROM users WHERE id = ?"deleteResult, err := db.Exec(deleteSql, 14)if err != nil {panic(err)}rowsAffected, _ = deleteResult.RowsAffected()fmt.Printf("影响行数:%d\n", rowsAffected)
}
如果你只想从数据表查询一行数据,可以调用QueryRow()和QueryRowContext()方法:
func (db *DB) QueryRow(query string, args ...any) *Row
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) *Row
上面的方法返回的是sql.Row对象,代表查询的那一行数据,这个对象只有Scan方法可以获取对象里的数据,调用Scan方法时传进去参数个数必须与查询返回的数据列数一致:
package mainimport ("database/sql""fmt"_ "github.com/mattn/go-sqlite3"
)func main() {db, err := sql.Open("sqlite3", "./test.db")if err != nil {panic(err)}defer db.Close()selectOne := "SELECT * FROM users WHERE id = ?"row := db.QueryRow(selectOne, 1)var (id intname stringgender uint8mobile string)//扫描数据err = row.Scan(&id, &name, &gender, &mobile)if err != nil {panic(err)}genderText := "未知"switch gender {case 1:genderText = "男"case 2:genderText = "女"}fmt.Printf("用户:%s | 性别:%s | 手机:%s\n", name, genderText, mobile)
}
然而,更多的时候,我们需要查询多行数据,可以调用Query()和QueryContext()方法:
func (db *DB) Query(query string, args ...any) (*Rows, error)
func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error)
上面两个方法返回的是sql.Rows对象,代表查询回来的多行数据,可以在for循环语句中通过Next()和Scan()方法扫描每一行数据,传给Scan方法的参数数量必须与查询回来的列数相同,另外,要记得调用Close()方法关闭sql.Rows对象:
package mainimport ("database/sql""fmt""log"_ "github.com/mattn/go-sqlite3"
)func main() {db, err := sql.Open("sqlite3", "./test.db")if err != nil {panic(err)}defer db.Close()selectMany := "SELECT * FROM users"rows, err := db.Query(selectMany)if err != nil {panic(err)}defer rows.Close()for rows.Next() {var (id intname stringgender uint8mobile string)if err := rows.Scan(&id, &name, &gender, &mobile); err != nil {log.Fatal(err)}genderText := "未知"switch gender {case 1:genderText = "男"case 2:genderText = "女"}fmt.Printf("用户:%s | 性别:%s | 手机:%s\n", name, genderText, mobile)}}
sql.Stmt
SQL语句预编译机制允许先把带有参数占位符的SQL语句发送给数据库,数据库会提前对SQL语句进行编译,之后我们再发送对应占位符的参数给数据库 。
SQL语句的好处在于:
- 预防SQL注入攻击。
- 复杂的SQL语句,提前编译提高SQL语句执行效率。
调用sql.DB、sql.Conn和sql.Tx(下面会讲到)的Prepare()方法或者PrepareContext()会返回一个sql.Stmt:
stmt, err := db.Prepare("INSERT INTO users(name,) VALUES(?,?,?),(?,?,?)")
因为SQL语句已经预发送给数据库,因此调用sql.Stmt的ExecXXX()和QueryXXX()时,只需要发送参数即可:
Stmt.Exec("张三",2,"10086","李四",1,"10086111")
sql.Stmt对象里的方法返回值与sql.DB一样是sql.Result,具体使用参考前面的例子。
sql.Tx
sql.Tx表示一个数据库事务对象,调用sql.DB或者sql.Conn对象的Begin()或者BeginTx()方法会返回一个sql.Tx:
tx,err := db.Begin()
sql.Tx与sql.DB执行CURD的方法基本相同,所不同的是,通过sql.Tx执行的语句,最后要调用sql.Tx的Commit()方法提交事务,如果执行时有错误发生,则应该调用Rollback()方法回滚事务:
package mainimport ("database/sql"_ "github.com/mattn/go-sqlite3"
)func main() {db, err := sql.Open("sqlite3", "./test.db")if err != nil {panic(err)}defer db.Close()tx, err := db.Begin()if err != nil {panic(err)}if _, err := tx.Exec("INSERT INTO users VALUES(?,?,?,?)", 1, "小龙", 1, "137xxxxxxxx"); err != nil {tx.Rollback()}if _, err := tx.Exec("INSERT INTO users VALUES(?,?,?,?)", 2, "小明", 1, "137xxxxxxxx"); err != nil {tx.Rollback()}tx.Commit()
}
总结
通过本文的学习,我们能够掌握Go语言数据库编程的基本技能,并能够独立进行数据库应用程序的开发。Go语言数据库编程是一个实践性很强的领域,需要不断地学习和实践。希望本文能够为你的学习之路提供指导和帮助。
简单总结一下:
- sql.DB对象表示一个数据库句柄,其中包含一个数据库连接池。
- sql.Conn对象表示一个连接池里的普通数据库连接。
- sql.Tx表示一个数据库事务对象,通过该对象执行的SQL语句要调用Commit()方法才会生效,如果执行过程发生错误,要调用Rollback()方法回滚事务。
- sql.Stmt表示一个预编译对象,通过这个对象执行的SQL语句会先发送给数据库,之后再发送参数,这样可以避免SQL注入以及提前编译语句,提高执行效率。
- sql.Rows是调用QueryXXX这类方法返回的表示多行数据的对象,内置迭代器,可以调用for语句迭代查询回来的数据。
- sql.Row是调用QueryRowXXX这类方法返回的对象,代表一行数据。
- sql.Result是调用ExecXXX这类方法进行update,delete,insert操作之后返回的结果。
相关文章:

Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。 Golang学习专栏:https://blog.csdn.net/qq_35716689/category_12575301.html 前言 对数据库…...

《游戏引擎架构》 -- 学习2
声明,定义,以及链接规范 翻译单元 声明与定义 链接规范 C/C 内存布局 可执行映像 程序堆栈 动态分配的堆 对象的内存布局 kilobyte 和 kibibyte 流水线缓存以及优化 未完待续。。。...

#Js篇:js里面递归的理解
定义: 递归是一种编程技术,它是指一个函数在其定义内部调用自身的过程。 特点: 一个问题可以分解为更小的问题用同样的方法解决;分解后的子问题求解方式一样,不同的是数据规模变小;存在递归终止条件 作…...

Qt博客目录
一.Qt安装配置和创建项目 Qt所有版本下载地址 Qt安装配置教程windows版(包括:Qt5.8.0版本,Qt5.12,Qt5.14版本下载安装教程)(亲测可行) QT从入门到入土(一)——Qt5.14.…...

【C++】初识模板:函数模板和类模板
目录 一、模板函数 1、函数模板的概念 2、函数模板的格式 3、函数模板的原理 4、函数模板实例化 5、 模板参数的匹配原则 二、类模板 1 、类模板的定义格式 2 、类模板的实例化 3、模板类示例 一、模板函数 1、函数模板的概念 函数模板代表了一个函数家族,…...

记录Dynamo每个节点的运行时间
不知道小伙伴们在写Dynamo程序的时候,有没有遇到这种问题→程序运行很慢,但是却不知道该优化哪些节点,可以提高程序运行的速度。 今天呢,就给大家分享一个节点包→TuneUp,在节点包管理器里就可以下载,安装…...

探索设计模式的魅力:代理模式揭秘-软件世界的“幕后黑手”
设计模式专栏:http://t.csdnimg.cn/U54zu 目录 引言 一、魔法世界 1.1 定义与核心思想 1.2 静态代理 1.3 动态代理 1.4 虚拟代理 1.5 代理模式结构图 1.6 实例展示如何工作(场景案例) 不使用模式实现 有何问题 使用模式重构示例 二、…...

AD9361多片同步设计方法
本文基于ZC706FMCOMMS5的平台,介绍了多片AD9361同步的方法。并将该设计移植到自行设计的ZYNQ70354片AD9361(实现8路同步收发)的电路板上。本设计采用纯逻辑的方式,仅使用了ZYNQ芯片的PL部分。 9361多芯片同步主要包括基带同步和射频同步两大块任务。其中…...

2024/2/7 图的基础知识
图的存储 B3643 图的存储 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路:mp[n][n]用来存邻接矩阵,二维vector用来存每个点连的点 完整代码: #include <bits/stdc.h> #define int long long const int N 1e5 10; int n, m; …...

1897_野火FreeRTOS教程阅读笔记_链表
1897_野火FreeRTOS教程阅读笔记_链表 全部学习汇总: g_FreeRTOS: FreeRTOS学习笔记 (gitee.com) 之前我自己通过直接啃代码的方式对FreeRTOS也算是有了一点理解了,这次趁着些许闲暇翻看一下野火的FreeRTOS教程。一者算是一种复习;二者可能对自…...

CTFshow web(php命令执行 45-49)
基础知识: 1.绕过cat使用: tac more less head tac tail nl od(二进制查看) vi vim sort uniq rev 2.绕过空格用: %09 <> ${IFS} $IFS$ {cat,fl*} %20 注: %09 ##(Tab) %20 ##(spa…...

飞天使-linux操作的一些技巧与知识点8-zabbix6.0 容器搭建
文章目录 安装docker安装步骤mysql下载镜像安装zabbix 使用zabbix非host模式创建 测试效果 安装docker 1. 配置官方 yum 源$ sudo yum install -y yum-utils $ sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo2. 安装 Docker$ …...

51 单片机入门 400 例
1 IO输出 点亮1个LED灯方法1 2 IO输出 点亮1个LED灯方法2 3 IO输出 点亮多个LED灯方法1 4 IO输出 点亮多个LED灯方法2 5 闪烁1个LED 6 不同频率闪烁1个LED灯 7 不同频率闪烁多个LED灯…...

贪心算法的应用
考虑最大利润 输入:种类数、需求量、各种类的库存量、各种类的总价 输出:最大利润 #include <iostream> #include <algorithm>//调用sort排序 using namespace std; struct mooncake{double store;double price;double tprice; }cake[1000]…...

CentOS基于volatility2的内存取证实验
CentOS,Redhat和Fedora 都是Red Hat体系,采用yum管理器,不同于Debian、Ubuntu作为Debian体系使用apt 本文以CentOS为例,采用avml制作内存镜像,并利用volatility官方所给工具制作profile符号文件,进行简单的…...

HLS 三角函数报错:undefined reference to ‘cordic_apfixed::circ_table_arctan_128‘
最近在通过HLS实现一些算法,其中用到了hls::cos函数,写完代码编译报错: ../Vitis_HLS/hls_cordic_apfixed.h:229: undefined reference to cordic_apfixed::circ_table_arctan_128 build/xf_computePhaseMap_accel.o: In function void cord…...

【汇编】简单的linux汇编语言程序
一、Linux系统汇编语言 Linux系统上的汇编语言可以使用不同的语法风格,主要包括Intel语法和AT&T语法。这两种语法有各自的特点和风格区别,尽管它们表示的底层机器指令相同。下面分别对两种语法进行简要说明: Intel语法 Intel语法是由I…...

Fink CDC数据同步(四)Mysql数据同步到Kafka
依赖项 将下列依赖包放在flink/lib flink-sql-connector-kafka-1.16.2 创建映射表 创建MySQL映射表 CREATE TABLE if not exists mysql_user (id int,name STRING,birth STRING,gender STRING,PRIMARY KEY (id) NOT ENFORCED ) WITH (connector mysql-cdc,hostn…...

Adb offline疑难杂症解决方案大全记录
无线/有线Adb offline依次尝试下面步骤: adb kill-server && adb start-server adb reconnect offline 多次 adb tcpip 5555 后重试 检查有线端口5037、无线5555占用,排除改名的adb或其他应用占用 换USB线和USB口拔插、确保同一WiFi下࿰…...

详述FlinkSql Join操作
FlinkSql 的 Join Flink 官网将其分为了 Joins 和 Window Joins两个大类,其中里面又分了很多 Join 方式 参考文档: Joins | Apache Flink Window JOIN | Apache Flink Joins 官网介绍共有6种方式: Regular Join:流与流的 Joi…...

Ajax+JSON学习二
AjaxJSON学习二 文章目录 前言三、前后端数据交互3.1. GET请求3.2. POST请求3.3. jQuery 中的 Ajax3.4. Ajax 的替代品:fetch3.5. 小结 四、JSON4.1. JSON简介4.2. JSON 语法规则4.3. JSON的解析和序列化 总结 前言 三、前后端数据交互 3.1. GET请求 GET 请求一般用…...

STM32单片机的基本原理与应用(六)
串口测试实验 基本原理 在串口实验中,是通过mini_USB线搭建终端与电脑端(也可称终端,为做区分称电脑端)的“桥梁”,电脑端的串口调试助手通过mini_USB线向终端发送信息,由CH340芯片将USB接口进行转换&…...

《MySQL 简易速速上手小册》第4章:数据安全性管理(2024 最新版)
文章目录 4.1 用户认证和权限控制4.1.1 基础知识4.1.2 重点案例:使用 Python 管理 MySQL 用户权限4.1.3 拓展案例 4.2 防止 SQL 注入和其他安全威胁4.2.1 基础知识4.2.2 重点案例:使用 Python 和 MySQL 进行安全的数据查询4.2.3 拓展案例 4.3 数据加密和…...

VUE学习之路——列表渲染
<p v-for"item in items">{{ item }}</p>使用v-for进行列表的渲染。 这仅仅是一个简单的demo,使用v-for可以用来遍历数组和对象,具体如下: 注意:遍历数组或对象的时候,()…...

CentOS 安装 redis 7.2
nginx官网 https://redis.io/download/ 把鼠标放到这里,复制下载地址 在服务器找个文件夹执行命令 wget https://github.com/redis/redis/archive/7.2.4.tar.gz tar -zxvf 7.2.4.tar.gz make make install 看到这几行就说明安装成功了 不放心的话再查看下b…...

运维自动化bingo前端
项目目录结构介绍 项目创建完成之后,我们会看到bingo_web项目其实是一个文件夹,我们进入到文件夹内部就会发现一些目录和文件,我们简单回顾一下里面的部分核心目录与文件。 ├─node_modules/ # node的包目录,项目运行的依赖包…...

Project2013下载安装教程,保姆级教程,附安装包和工具
前言 Project是一款项目管理软件,不仅可以快速、准确地创建项目计划,而且可以帮助项目经理实现项目进度、成本的控制、分析和预测,使项目工期大大缩短,资源得到有效利用,提高经济效益。软件设计目的在于协助专案经理发…...

【机器学习与自然语言处理】预训练 Pre-Training 各种经典方法的概念汇总
【机器学习与自然语言处理】预训练 Pre-Training 各种经典方法的概念汇总 前言请看此正文预训练 Pre-Training无监督学习 unsupervised learning概念:标签PCA 主成分分析(Principal Component Analysis)降维算法LSA 潜在语义分析(…...

Mac电脑如何通过终端隐藏应用程序?
在我们使用Mac电脑的时候难免会遇到想要不想看到某个应用程序又不想卸载它们。值得庆幸的是,macOS具有一些强大的文件管理功能,允许用户轻松隐藏(以及稍后显示)文件甚至应用程序。 那么,Mac电脑如何通过终端隐藏应用程…...

linker list
linker list是利用lds 描述符实现同类型数据连续排布的一种机制。 下面是uboot里面的应用说明 lds文件里面需要增加section描述: . ALIGN(4);.u_boot_list : {KEEP(*(SORT(.u_boot_list*)));}linker_list.h: /* SPDX-License-Identifier: GPL-2.0 */ /** include…...