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/sql在database/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开发的后端数据库存储引擎。欢迎大家期待与认可
在此谢谢大家的支持,你的关注和点赞会是我继续努力写文章的动力,也感谢大家能够持续关注博主,谢谢大家的支持,周末会给大家写一篇福利文章,大家敬请期待~~~
相关文章:
GO语言学习(九)
GO语言学习(九) 上一期我们了解了实现web的工作中极为重要的net/http抱的细节讲解,大家学会了实现web开发的一些底层基础知识,在这一期我来为大家讲解一下web工作的一个重要方法,:使用数据库,现…...

go 访问 sftp 服务 github.com/pkg/sftp 的使用踩坑,连接未关闭(含 sftp 服务测试环境搭建)
前言 最近在使用 sftp 服务时,被告知发起了海量的连接,直接把服务器搞崩,ip 被封了。 这是啥情况? golang 写的代码,我就正常的访问 sftp 服务,连接使用过后也都关闭了,咋会出现连接一直连着…...

Linux多线程(二)之进程vs线程
文章目录 Linux进程VS线程进程和线程进程的多个线程共享关于进程线程的问题 重谈地址空间Linux线程周边的概念 Linux进程VS线程 进程和线程 进程是资源分配的基本单位(进程是承担分配系统资源的基本实体) 执行流也是资源!线程是进程内部的执…...
【MogDB】测试 ubuntu server 22.04 LTS 安装mogdb 5.0.11
测试 ubuntu server 22.04 LTS 安装mogdb 5.0.11 使用的操作系统镜像是 https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso 装好操作系统后,把root登录打开了,方便后续操作。 测试过程 使用官方命令在线安装ptk rootubuntu22…...
AI时代新词-数字孪生(Digital Twin)
一、什么是数字孪生(Digital Twin)? 数字孪生(Digital Twin)是一种通过创建物理实体的虚拟副本,并利用数据和算法来模拟、分析和优化物理实体的性能和行为的技术。数字孪生结合了物联网(IoT&am…...

【HW系列】—web常规漏洞(文件上传漏洞)
文章目录 一、简介二、危害三、文件检测方式分类四、判断文件检测方式五、文件上传绕过技术六、漏洞防御措施 一、简介 文件上传漏洞是指Web应用程序在处理用户上传文件时,未对文件类型、内容、路径等进行严格校验和限制,导致攻击者可上传恶意文件&…...

如何实现 C/C++ 与 Python 的通信
C/C 与 Python 的通信可以通过多种方式实现,如使用 C API、Ctypes、Cython、SWIG、Python.h 或基于共享库的调用等。其中,使用 Ctypes 方式最为简便,适合快速调用已有的 C 函数库。例如,通过将 C 代码编译为动态链接库(…...
python炸鱼船
import pygame, random # 加载库 from pygame.locals import * pygame.init() pygame.display.set_caption("炸渔船") canvas pygame.display.set_mode((700, 500)) bgpygame.image.load("bg.png") bgpygame.transform.scale(bg,(700,500))class Hero(py…...
使用AutoKeras2.0的AutoModel进行结构化数据回归预测
1、First of All: Read The Fucking Source Code import autokeras as ak import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error# 生成数据集 np.random.seed(42) x np.random.rand(1000, 10) # 生成1…...

好用但不常用的Git配置
参考文章 文章目录 tag标签分支新仓库默认分支推送 代码合并冲突处理默认diff算法 tag标签 默认是以字母顺序排序,这会导致一些问题,比如0.5.101排在0.5.1000之后。为了解决这个问题,我们可以把默认排序改为数值排序 git config --global t…...

ULVAC VWR-400M/ERH 真空蒸发器 Compact Vacuum Evaporator DEPOX (VWR-400M/ERH)
ULVAC VWR-400M/ERH 真空蒸发器 Compact Vacuum Evaporator DEPOX (VWR-400M/ERH)...
P1068 [NOIP 2009 普及组] 分数线划定
题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行。为了选拔最合适的人才,A 市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的 150% 划定,即如果计划录取 m 名志愿者…...

PPT连同备注页(演讲者模式)一块转为PDF
首先,进入创建PDF/XPS: 然后进入选项: 发布选项-发布内容里选备注页: 导出的原始结果是这样的: 这个时候裁剪一下,范围为所有页面: 最终结果: 如果导出不选“备注页”而是只勾选“包…...
第三十二天打卡
作业:参考pdpbox官方文档中的其他类,绘制相应的图,任选即可 1. 安装并导入库 确保安装与文档版本一致的 pdpbox(此处以 0.3.0 为例): bash 复制 下载 pip install pdpbox0.3.0 导入所需库:…...

项目三 - 任务8:实现词频统计功能
本项目旨在实现一个词频统计功能,通过读取文本文件并利用Java编程技巧处理和分析文本数据。首先,使用BufferedReader逐行读取文件内容,然后通过String.split(" ")方法将每行文本分割成单词数组。接下来,采用HashMap来存…...
MongoDB 快速整合 SpringBoot 示例
1.添加依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spr…...
2025.05.22-得物春招机考真题解析-第二题
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 02. 魔法书页重排 问题描述 A先生是一位魔法师,他有一本古老的魔法书,书中有 n n n 页,每页都刻有一个魔…...

ollama list模型列表获取 接口代码
ollama list模型列表获取 接口代码 curl http://localhost:11434/v1/modelscoding package hcx.ollama;/*** ClassName DockerOllamaList* Description TODO* Author dell* Date 2025/5/26 11:31* Version 1.0**/import java.io.BufferedReader; import java.io.InputStreamR…...

OPC Client第5讲(wxwidgets):初始界面的事件处理;按照配置文件初始化界面的内容
接上一讲,即实现下述界面的事件处理代码;并且按照配置文件初始化界面的内容(三、) 事件处理的基础知识,见下述链接五、 OPC Client第3讲(wxwidgets):wxFormBuilder;基础…...
什么是BFC,如何触发BFC,BFC有什么特性?
理解 BFC指的是块级格式化上下文,处于BFC内部的盒子与外界互不影响 触发条件 position:absolute/fixed都会产生bfcdisplay:inline-block,table,flex等float:left/right 浮动也会产生bfchtml根元素也是bfc bfc的特性 属于同一个BFC下的盒子会垂直排列属于同一个BFC下的两个…...
python做题日记(9)
第二十一题 第二十一题是合并两个有序链表,合并后的链表仍然需要保持有序,因为在合并之前已经是两个有序链表,因此在合并时只需要遍历比较两个链表中的下一结点数值,将其中较小的一个结点添加到新的列表中。如果有任何一个链表已经…...
Leetcode 3557. Find Maximum Number of Non Intersecting Substrings
Leetcode 3557. Find Maximum Number of Non Intersecting Substrings 1. 解题思路2. 代码实现 题目链接:3557. Find Maximum Number of Non Intersecting Substrings 1. 解题思路 这一题就是一个比较直接的动态规划的题目,我们只需要考察每一个位是否…...

【C++进阶篇】初识哈希
哈希表深度剖析:原理、冲突解决与C容器实战 一. 哈希1.1 哈希概念1.2 哈希思想1.3 常见的哈希函数1.3.1 直接定址法1.3.2 除留余数法1.3.3 乘法散列法(了解)1.3.4 平方取中法(了解) 1.4 哈希冲突1.4.1 冲突原因1.4.2 解…...

Spring Boot——自动配置
目录 1.bean加载方式 1.1XML方式声明bean 1.2 xml 注解方式声明bean 1.3通过Configuration和Bean 1.4使用Import注解 1.5使用上下文对象在容器初始化完毕后注入bean 1.6使用ImportSelector接口 1.7实现ImportBeanDefinitionRegistrar接口 1.8bean加载方式(…...
免费轻量便携截图 录屏 OCR 翻译四合一!提升办公效率
各位软件小达人们,今天来给大伙唠唠VeryCapture这款软件! 先说说它的核心功能。这软件有个超厉害的多模态屏幕捕捉系统,它就像个全能小能手,把截图、录屏、OCR文字识别、翻译这些功能全集成在一起啦!截图有6种模式&a…...

使用 Vuex 实现用户注册与登录功能
引言 在构建具有用户认证功能的应用时,Vuex 可以用来管理用户的登录状态和相关信息。以下是如何使用 Vuex 来实现用户注册与登录功能的概述。 🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端…...

进程通信(管道,共享内存实现)
01. 进程通信简介 进程通信工具分为数据传输工具和共享内存两类。这里我们讨论进程通信工具(IPC)里面的管道、system V和共享内存。在理解阶层通信之间,我们先了解用户空间缓冲区和内核空间缓冲区两个概念。 1.1 用户空间缓冲区 存在于用户态的进程用户空间&#…...

电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测
电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测 目录 电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测预测效果基本描述程序设计参考资料 预测效果 基本描述 电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测 运行环境Matlab2023b及以上,锂电池剩余寿…...

快速上手SHELL脚本常用命令
一、设置主机名称 1.修改文件方式 重启后生效 2.命令修改 重启shell后生效 二、网卡管理nmcli 1.查看网卡 2.设置网卡 详细配置:快速上手Linux联网管理-CSDN博客 三、简单处理字符 1.打印连续数字 2.设置字体颜色 \033[颜色代号m 3.反向打印文件内容 tac&a…...
【无标题】前端如何实现分页?
前端如何实现分页? 以下是对代码的逐条总结与解释,按 HTML、JavaScript、CSS 顺序分模块列出,每条代码单独说明: 一、HTML 代码解释 1. 表格容器 html <table class"table table-bordered table-hover">作用&…...