GO语言学习(九)

GO语言学习(九)

上一期我们了解了实现web的工作中极为重要的net/http抱的细节讲解,大家学会了实现web开发的一些底层基础知识,在这一期我来为大家讲解一下web工作的一个重要方法,:使用数据库,现在就让我来为大家讲解这一篇章,欢迎大家交流学习

sql接口及database

首先和大家解释一下在golang中没有提供现成的数据库驱动方式,英雌在我们实际开发中一般是实现接口,利用这些接口来实现相应的数据库驱动操作,这样使用可以在迁移数据库的时候,只用使用开发好的标准数据库接口。

sql.register说明

这个存在于database/sql的函数是用来注册数据库驱动的,当第三方开发者开发数据库驱动时,都会实现init函数,在init里面会调用这个Register(name string, driver driver.Driver)完成本驱动的注册。

我们来看一下mysql、sqlite3的驱动里面都是怎么调用的,下面直接上代码:

// 实现示例:
//https://github.com/mattn/go-sqlite3驱动
func init() {sql.Register("sqlite3", &SQLiteDriver{})
}//https://github.com/mikespook/mymysql驱动
// Driver automatically registered in database/sql
var d = Driver{proto: "tcp", raddr: "127.0.0.1:3306"}
func init() {Register("SET NAMES utf8")sql.Register("mymysql", &d)
}

**我们看到第三方数据库驱动都是通过调用这个函数来注册自己的数据库驱动名称以及相应的driver实现。在database/sql内部通过一个map来存储用户定义的相应驱动。**示例说明:

var drivers = make(map[string]driver.Driver)drivers[name] = driver

因此通过database/sql的注册函数可以同时注册多个数据库驱动,只要不重复。

我们一般通过使用以下代码来使用相应的接口和第三方库

  import ("database/sql"_ "github.com/mattn/go-sqlite3")
一般的新手都会被这个_所迷惑,其实这个就是Go设计的巧妙之处,我们在变量赋值的时候经常看到这个符号,它是用来忽略变量赋值的占位符,那么包引入用到这个符号也是相似的作用,这儿使用_的意思是引入后面的包名而不直接使用这个包中定义的函数,变量等资源。同时我们引入上面的数据库驱动包之后会自动去调用init函数,然后在init函数里面注册这个数据库驱动,这样我们就可以在接下来的代码中直接使用这个数据库驱动了。

driver.Driver讲解

Driver是一个数据库驱动的接口,他定义了一个method: Open(name string),这个方法返回一个数据库的Conn接口。

type Driver interface {Open(name string) (Conn, error)
}

返回的Conn只能用来进行一次goroutine的操作,也就是说不能把这个Conn应用于Go的多个goroutine里面。如下代码会出现错误,如下所示:

...
go goroutineA (Conn)  //执行查询操作
go goroutineB (Conn)  //执行插入操作
...

上面这样的代码可能会使Go不知道某个操作究竟是由哪个goroutine发起的,从而导致数据混乱,比如可能会把goroutineA里面执行的查询操作的结果返回给goroutineB从而使B错误地把此结果当成自己执行的插入数据。

第三方驱动都会定义这个函数,它会解析name参数来获取相关数据库的连接信息,解析完成后,它将使用此信息来初始化一个Conn并返回它。

driver.Conn说明

Conn是一个数据库连接的接口定义,他定义了一系列方法,这个Conn只能应用在一个goroutine里面,不能使用在多个goroutine里面.

type Conn interface {Prepare(query string) (Stmt, error)Close() errorBegin() (Tx, error)
}
  • **1.**Prepare函数返回与当前连接相关的执行Sql语句的准备状态,可以进行查询、删除等操作。

    **2.**Close函数关闭当前的连接,执行释放连接拥有的资源等清理工作。因为驱动实现了database/sql里面建议的conn pool,所以你不用再去实现缓存conn之类的,这样会容易引起问题。

    **3.**Begin函数返回一个代表事务处理的Tx,通过它你可以进行查询,更新等操作,或者对事务进行回滚、递交。

driver.Stimt详解

**Stmt是一种准备好的状态,和Conn相关联,而且只能应用于一个goroutine中,不能应用于多个goroutine。**实现代码如下:

type Stmt interface {Close() errorNumInput() intExec(args []Value) (Result, error)Query(args []Value) (Rows, error)
}
  • Close函数关闭当前的链接状态,但是如果当前正在执行query,query还是有效返回rows数据。

  • NumInput函数返回当前预留参数的个数,当返回>=0时数据库驱动就会智能检查调用者的参数。当数据库驱动包不知道预留参数的时候,返回-1。

  • Exec函数执行Prepare准备好的sql,传入参数执行update/insert等操作,返回Result数据

  • Query函数执行Prepare准备好的sql,传入需要的参数执行select操作,返回Rows结果集

driver.Tx解释

事务处理一般就两个过程,递交或者回滚。数据库驱动里面也只需要实现这两个函数就可以,代码如下:

type Tx interface {Commit() errorRollback() error
}

**这两个函数一个用来递交一个事务,一个用来回滚事务。**大家可以在实际开发中感受一下这个的独特特性,不懂的欢迎大家在评论区中分享,大家一起讨论。

driver.Execer讲解

driver.Execer是一个Conn可选择实现的接口,功能有许多好的妙用,如果未使用这个接口,那么在调用DB.Exec,就会首先调用Prepare返回Stmt,然后执行Stmt的Exec,然后关闭Stmt。下面提供实现这个接口的示例代码:

type Execer interface {Exec(query string, args []Value) (Result, error)
}

driver.Result讲解

driver.Result是执行Update/Insert等操作返回的结果接口定义,LastInsertId函数返回由数据库执行插入操作得到的自增ID号RowsAffected函数返回执行Update/Insert等操作影响的数据条目数。下面我们来为大家提供一下示例代码:

type Result interface {LastInsertId() (int64, error)RowsAffected() (int64, error)
}

driver.Rows讲解

其实Rows是执行查询返回的结果集接口定义,Columns函数返回查询数据库表的字段信息,这个返回的slice和sql查询的字段一一对应,而不是返回整个表的所有字段。Close函数用来关闭Rows迭代器。Next函数用来返回下一条数据,把数据赋值给dest。dest里面的元素必须是driver.Value的值除了string,返回的数据里面所有的string都必须要转换成[]byte。如果最后没数据了,Next函数最后返回io.EOF。示例代码如下:

type Rows interface {Columns() []stringClose() errorNext(dest []Value) error
}

driver.RowsAffected讲解

RowsAffected其实就是一个int64的别名,但是他实现了Result接口,用来底层实现Result的表示方式,代码如下:

type RowsAffected int64func (RowsAffected) LastInsertId() (int64, error)func (v RowsAffected) RowsAffected() (int64, error)

driver.Value讲解

Value其实就是一个空接口,他可以容纳任何的数据,然后其实就是drive的Value是驱动必须能够操作的Value,Value要么是nil,要么是下面的给出的数据类型。

type Value interface{} // 构建value接口// 数据类型
int64
float64
bool
[]byte
string   [*]除了Rows.Next返回的不能是string.
time.Time

database/sql说明

database/sqldatabase/sql/driver提供的接口基础上定义了一些更高阶的方法,用以简化数据库操作,同时内部还建议性地实现一个conn. pool,然后我们就可以得出一下结论,大家可以自己先思考一下,在结合我给的讲解:

我们可以看到Open函数返回的是DB对象,里面有一个freeConn,它就是那个简易的连接池。它的实现相当简单或者说简陋,就是当执行db.prepare -> db.prepareDC的时候会defer dc.releaseConn,然后调用db.putConn,也就是把这个连接放入连接池,每次调用db.conn的时候会先判断freeConn的长度是否大于0,大于0说明有可以复用的conn,直接拿出来用就是了,如果不大于0,则创建一个conn,然后再返回之。

看完这些我在给大家提供代码,大家可以参考,然后自己在试着敲敲下面的示例代码:

type DB struct {driver 	 driver.Driverdsn    	 stringmu       sync.Mutex // protects freeConn and closedfreeConn []driver.Connclosed   bool
}

结语

我们这一期简单的学习了一下数据库连接的接口实现,并且为大家讲解了些许的相关接口的实现,还有更多的知识大家需要自探索,后面我也会出一个专题来为大家详细解释的。

下一期我会为大家讲解实现MYSQL数据库,同时作为目前Internet上流行的网站构架方式是LAMP,其中的M即MySQL, 作为数据库,MySQL以免费、开源、使用方便为优势成为了很多Web开发的后端数据库存储引擎。欢迎大家期待与认可

在此谢谢大家的支持,你的关注和点赞会是我继续努力写文章的动力,也感谢大家能够持续关注博主,谢谢大家的支持,周末会给大家写一篇福利文章,大家敬请期待~~~

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

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

相关文章

解决MybatisPlus使用Druid1.2.11连接池查询PG数据库报Merge sql error的一种办法

目录 前言 一、问题重现 1、环境说明 2、重现步骤 3、错误信息 二、关于LATERAL 1、Lateral作用场景 2、在四至场景中使用 三、问题解决之道 1、源码追踪 2、关闭sql合并 3、改写处理SQL 四、总结 前言 在博客:【写在创作纪念日】基于SpringBoot和PostG…

嵌入式学习--江协51单片机day8

这个本来应该周末写的,可是一直想偷懒,只能是拖到周一了,今天把51结个尾,明天开始学32了。 学习内容LCD1602,直流电机,AD/DA,红外遥控 LCD1602 内部的框架结构 屏幕小于数据显示区&#xff…

HUAWEI华为MateBook D 14 2021款i5,i7集显非触屏(NBD-WXX9,NbD-WFH9)原装出厂Win10系统

适用型号:NbD-WFH9、NbD-WFE9A、NbD-WDH9B、NbD-WFE9、 链接:https://pan.baidu.com/s/1qTCbaQQa8xqLR-4Ooe3ytg?pwdvr7t 提取码:vr7t 华为原厂WIN系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、Office…

【Python】Python 装饰器的用法总结

在 Python 中,装饰器(Decorator) 是一种设计模式,用于在不修改函数或类代码的情况下动态地扩展其功能。装饰器广泛应用于日志记录、性能监控、权限验证等场景,提供了一种简洁优雅的方式来“包裹”现有的代码。本文将介…

【C++】控制台小游戏

移动&#xff1a;W向上&#xff0c;S上下&#xff0c;A向左&#xff0c;D向右 程序代码&#xff1a; #include <iostream> #include <conio.h> #include <windows.h> using namespace std;bool gameOver; const int width 20; const int height 17; int …

「MATLAB」计算校验和 Checksum

什么是校验和 是一个算法&#xff0c;将一串数据累加&#xff0c;得到一个和。 MATLAB程序 function c_use Checksum(packet) %Checksum 求校验和 % 此处checksum提供详细说明checksum 0;for i 1:length(packet)value hex2dec(packet(i));checksum checksum value; …

JavaScript面试题之消息队列

JavaScript消息队列详解&#xff1a;单线程的异步魔法核心 在JavaScript的单线程世界中&#xff0c;消息队列&#xff08;Message Queue&#xff09;是实现异步编程的核心机制&#xff0c;它像一位高效的调度员&#xff0c;让代码既能“一心多用”又避免卡顿。本文将深入剖析消…

京东外卖分润系统部署实操!0门槛入驻+全平台接入+自定义比例...这些人,赚翻了!

随着京东外卖的发展势头日渐迅猛&#xff0c;许多创业者们的态度也逐渐从原本的观望转变为了切实的行动&#xff0c;并开始通过各个渠道询问起了京东外卖自动分润系统部署相关的各项事宜&#xff0c;连带着以京东外卖自动分润系统质量哪家强为代表的多个问题&#xff0c;也成为…

【办公类-18-06】20250523(Python)“口腔检查涂氟信息”批量生成打印(学号、姓名、学校、班级、身份证、户籍、性别、民族)

背景需求: 6月是常规体检,前几天发了体检表(验血单),用Python做了姓名等信息的批量打印 【办公类-18-04】20250520(Python)“验血单信息”批量生成打印(学校、班级、姓名、性别)-CSDN博客文章浏览阅读969次,点赞19次,收藏11次。【办公类-18-04】20250520(Python)…

Python邮件处理:POP与SMTP

poplib简介 poplib 是Python 3中的官方邮件库&#xff0c;实现了POP的标准&#xff1a;RFC1939&#xff0c;用于邮件的收取。与之类似的还有imaplib 。 &#xff08;注&#xff1a;本文仅拿pop举例&#xff09; poplib的使用方法&#xff0c;就是几步&#xff1a; 先创建一…

IP风险度自检,多维度守护网络安全

如今IP地址不再只是网络连接的标识符&#xff0c;更成为评估安全风险的核心维度。IP风险度通过多维度数据建模&#xff0c;量化IP地址在网络环境中的安全威胁等级&#xff0c;已成为企业反欺诈、内容合规、入侵检测的关键工具。据Gartner报告显示&#xff0c;2025年全球78%的企…

Flink集成资源管理器

Flink集成资源管理器 Apache Flink 支持多种资源管理器&#xff0c;主要包括以下几种‌&#xff1a; YARN ResourceManager ‌&#xff1a;适用于使用 Hadoop YARN 作为资源管理器的环境。YARN ResourceManager 负责管理集群中的资源&#xff0c;包括 CPU、内存等&#xff0c;并…

upload 文件上传审计

目录 LOW Medium HIgh Impossible 概述 很多Web站点都有文件上传的接口&#xff08;比如注册时上传头像等&#xff09;&#xff0c;由于没有对上传的文件类型进行严格限制&#xff0c;导致可以上传一些文件&#xff08;比如Webshell&#xff09;。 上传和SQL、XSS等都是主流…

【freertos-kernel】list

freertos list 基本类型结构体ListItem_t &#xff08;list.h&#xff09;List_t &#xff08;list.h&#xff09; 宏函数函数vListInitialisevListInitialiseItemvListInsertEndvListInsertuxListRemove 基本类型 freertos为了兼容性&#xff0c;重新定义了基本类型&#xff…

游戏盾的功有哪些?

游戏盾的功能主要包括以下几方面&#xff1a; 一、网络攻击防护 DDoS攻击防护&#xff1a; T级防御能力&#xff1a;游戏盾提供分布式云节点防御集群&#xff0c;可跨地区、跨机房动态扩展防御能力和负载容量&#xff0c;轻松达到T级别防御&#xff0c;有效抵御SYN Flood、UD…

PycharmFlask 学习心得:路由(3-4)

对路由的理解&#xff1a; 用户输入网址 例如&#xff1a;http://localhost:5000/hello 浏览器会向这个地址发起一个 HTTP 请求&#xff08;比如 GET 请求&#xff09; 请求到达 Flask 的服务器 Flask 监听着某个端口&#xff08;如 5000&#xff09;&#xff0c;收到请求后…

课程与考核

6.1 课程讲解与实战考核 6.1.1 SQL注入篇考核 考核目标&#xff1a;通过手动注入与工具结合&#xff0c;获取目标数据库敏感信息。 题目示例&#xff1a; 目标URL&#xff1a;http://vuln-site.com/product?id1 要求&#xff1a; 判断注入类型&#xff08;联合查询/报错注…

线程池介绍,分类,实现(工作原理,核心组成,拒绝策略),固态线程池的实现+详细解释(支持超时取消机制和不同的拒绝策略)

目录 线程池 介绍 分类 实现 工作原理 核心组成 拒绝策略 固态线程池 功能 std::future 实现 拒绝策略支持 提交任务 超时取消 用户检测取消 安全销毁 代码 测试 线程池 介绍 线程池(图解,本质,模拟实现代码),添加单例模式(懒汉思路代码)_线程池单例-CSDN博…

纺线机与PLC通讯故障?ETHERCAT/CANopen网关秒解协议难题

在纺织行业智能化转型浪潮中&#xff0c;设备间高效通信是实现自动化生产的关键。JH-ECT009疆鸿智能EtherCAT转CANopen协议转换网关&#xff0c;凭借出色的协议适配能力&#xff0c;成功架起倍福PLC与自动纺线机间的通信桥梁&#xff0c;为纺织厂自动化生产注入强劲动力。 纺织…

深度剖析并发I/O模型select、poll、epoll与IOCP核心机制

核心概要&#xff1a;select、poll、epoll 和 IOCP 是四种用于提升服务器并发处理能力的I/O模型或机制。前三者主要属于I/O多路复用范畴&#xff0c;允许单个进程或线程监视多个I/O流的状态&#xff1b;而 IOCP 则是一种更为彻底的异步I/O模型。 一、引言&#xff1a;为何需要这…