Golang with SQLLite Practice

简介: golang 与sqllite 实战

1.1. 简介

SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,你不需要在系统中配置。在 Golang 中使用SQLLite 也相当简单,只需要安装 SQLLite 的Golang 包即可使用;
Golang 就不多介绍了,能看到这个肯定对 Golang 有一定的了解。

仓库地址:https://github.com/AndorLab/golang-sqllite

1.2. 目标

使用 SQLLite 通过构建一个社区用户表,包含如下字段; 通过 SQLLite 的 API 实现对社区用户表进行增删改查。

序号 字段 类型 说明
1 uid int64 id
2 username string 用户名
3 city string 城市
4 skills string 技能
5 created int64 创建时间

1.3. 目的

了解 SQLLite ,学习 Golang 操作 SQLLite, 巩固 Golang 基础知识。

1.4. Coding

1.4.1. 目录结构

项目采用 Golang 传统的平铺式目录

.
├── LICENSE
├── Makefile      # 构建工具
├── README.md     # README
├── db.go         # 数据库操作
├── error.go      # 错误处理工具方法
├── fcc.db        # sqllite 数据库
├── go.mod        # go modules
├── go.sum        # go modules
├── main.go       # 项目入口
├── server.go     # 应用程序入口
└── userModel.go  # 用户模型

1.4.2. 封装 error 函数

因为在 go 中会有很多的 error 的判断,为了代码精简,我们特封装一下 error; 下面的 interface{} 代表任何类型,类似 TypeScript 中的 any

# error.go
func checkErr(data interface{}, err error) (interface{}, error) {
    if err != nil {
        log.Error(err)
        return nil, err
    }
    return data, err
}

1.4.3. 安装 SQLLite 库及其他库

使用 go modules 之后,将所需的包放在 import 中,使用 go mod tidy 命令后,go 会自动安装程序使用到的包。

日志相关的库,主要用于在控制台打印结果

# server.go
import (
    "github.com/labstack/gommon/log"
)

SQLLite 包

# db.go
_ "github.com/mattn/go-sqlite3"

1.4.4. 申明 DB 全局变量

因为在程序中,我们要通过数据库来获取数据,那么存在一个全局的数据库指针是很有必要的。

# main.go
var db = new(sql.DB)

1.4.5. 初始化数据库

SQLLite 初始化数据库非常简单,只要指定数据库驱动和数据库文件就可以。为了在程序的整个生命周期中操作数据库,我们将 db 返回。

// openDB 打开数据库
func openDB() *sql.DB {
    //打开数据库,如果不存在,则创建
    db, err := sql.Open("sqlite3", "./fcc.db")
    checkErr(db, err)
    return db
}

创建好 db 后,需要创建表结构,执行如下数据库操作命令即可完成用户表的创建。

// initDB 初始化数据库
func initDB() {
    //创建表
    sqlTable := `
            CREATE TABLE IF NOT EXISTS userinfo(
                    uid INTEGER PRIMARY KEY AUTOINCREMENT,
                    username VARCHAR(64) NULL,
                    city VARCHAR(64) NULL,
                    skills VARCHAR(128) NULL,
                    created BIGINT NULL
            );
            `
    db.Exec(sqlTable)
}

1.4.6. 用户模型构建及原子操作

构建现代程序,强调程序的健壮性,封装就是比较重要的;用 MVC、 MVVM 的观点,我们需要有一个 Model 来提供对象的原子操作。在这,我们将用户抽象为UserModel,对用户的增删改查封装到 insertdleeteupdatequery

1.4.6.1. 用户模型

// UserModel 用户模型
type UserModel struct {
    uid      int64
    username string
    city     string
    skills   string
    created  int64
}

对用户的原子操作

1.4.6.2. 新增

// insert 新增
func (u UserModel) insert() (sql.Result, error) {
    stmt, err := db.Prepare("insert into userinfo(username, city, skills, created) values(?,?,?,?)")
    checkErr(stmt, err)
    res, err := stmt.Exec(u.username, u.city, u.skills, time.Now().Unix())
    checkErr(res, err)
    return res, nil
}

1.4.6.3. 删除

// delete 删除
func (u UserModel) delete(id int64) int64 {
    stmt, err := db.Prepare("delete from userinfo where uid=?")
    checkErr(stmt, err)
    res, err := stmt.Exec(id)
    checkErr(res, err)
    affect, err := res.RowsAffected()
    checkErr(affect, err)
    return affect
}

1.4.6.4. 修改

// update    更新用户技能
func (u UserModel) update(id int) int64 {
    stmt, err := db.Prepare("update userinfo set skills=? where uid=?")
    checkErr(stmt, err)
    res, err := stmt.Exec(u.skills, id)
    checkErr(res, err)
    affect, err := res.RowsAffected()
    checkErr(affect, err)
    return affect
}

1.4.6.5. 查询

// query 查询
func (u UserModel) query() ([]UserModel, error) {
    rows, err := db.Query("select * from userinfo")
    checkErr(rows, err)
    var userList = []UserModel{}
    for rows.Next() {
        var user = UserModel{}
        err = rows.Scan(&user.uid, &user.username, &user.city, &user.skills, &user.created)
        checkErr(nil, err)
        userList = append(userList, user)
    }
    rows.Close()
    return userList, nil
}

1.4.7. 在应用中启动并调用用户模型的方法

在上面我们完成了对用户模型及原子操作的封装,那么接下来就是通过应用程序将分装的内容调用,传入正确的参数进行调用。
我们在此封装一个 startAPP 方法,在这个里面我们调用封装好的用户操作的接口,实现功能。

因为数据库要在整个生命周期存在,当程序结束的时候,我们应该将数据库链接释放,所以我们用到了 go 的 defer 关键字

# server.go
  db = openDB()
  defer db.Close()
  initDB()

调用用户操作的增删改查并打印结果, 对于不同的操作,我们应该有不同的数据,所以在程序中会有 user、和 updateUser 两个对象

# server.go
  user := UserModel{
      username: "谷中仁",
      city:     `西安`,
      skills:   `TypeScript`,
  }
  // insert
  result, err := user.insert()
  id, err := result.LastInsertId()
  checkErr(id, err)
  log.Info("增:操作数据的id:", id)
  // update
  updateUser := UserModel{
      skills: `golang`,
  }
  affectedRow := updateUser.updateSkills(1)
  log.Info("改:影响的行数:", affectedRow)
  // query
  queryUser := UserModel{}
  list, _ := queryUser.query()
  log.Info("查:", list)
  // delete
  affect := queryUser.delete(1)
  log.Info("删:", affect)  
  // query
  list, _ = queryUser.query()
  log.Info("查:", list)

1.4.8. 运行结果展示

$ make run
go run *.go
{"time":"2019-08-31T14:21:48.941164+08:00","level":"INFO","prefix":"-","file":"server.go","line":"21","message":"增:操作数据的id:1"}
{"time":"2019-08-31T14:21:48.941842+08:00","level":"INFO","prefix":"-","file":"server.go","line":"27","message":"改:影响的行数:1"}
{"time":"2019-08-31T14:21:48.942034+08:00","level":"INFO","prefix":"-","file":"server.go","line":"31","message":"查:[{1 谷中仁 西安 golang 1567232508}]"}
{"time":"2019-08-31T14:21:48.942599+08:00","level":"INFO","prefix":"-","file":"server.go","line":"34","message":"删:1"}
{"time":"2019-08-31T14:21:48.942696+08:00","level":"INFO","prefix":"-","file":"server.go","line":"38","message":"查:[]"}

1.5. 总结

SQLLite 对开发者非常友好,不用安装在机器上,只要指定SQLLite的驱动和数据库存储文件即可对 SQLLite 数据库进行操作;Golang 作为比较流行的语言,对数据库也非常友好,提供了基本的数据库接口,
至于用户需要什么样的数据库,自己开发对应的数据库驱动即可。当然在 GitHub 已经有很多开源爱好者开发了比较流行的数据库的驱动可以直接拿来用。

SQLLite 使用的也是标准的 SQL 语法,可以让不同的开发者快速入手。

为什么没有用到 Golang 的 Web 框架?

因为我们的侧重点在 Golang 与 SQLLite,不在 API 实现上,最小化的实现目标,才是我们学习知识最快速的途径。

原文链接:https://chinese.freecodecamp.org/news/golang-with-sqllite-practice/

目录
相关文章
|
NoSQL Java Go
记一次Golang内存分析——基于go pprof
## 1. 背景 阿里云Redis线上在某些任务流中使用`redis-port`来进行实例之间的数据同步。`redis-port`是一个MIT协议的开源软件,主要原理是从源实例读取RDB快照文件、解析、然后在目标实例上应用灌数据的写命令。为了限制每个进程的最大内存使用,我们使用cgroup来做隔离,最近线上出现redis-port在同步数据时`OOM`的情况,最高内存使用达到了`10G`以上
25156 0
|
4天前
|
存储 Cloud Native Shell
go库介绍:Golang中的Viper库
Viper 是 Golang 中的一个强大配置管理库,支持环境变量、命令行参数、远程配置等多种配置来源。本文详细介绍了 Viper 的核心特点、应用场景及使用方法,并通过示例展示了其强大功能。无论是简单的 CLI 工具还是复杂的分布式系统,Viper 都能提供优雅的配置管理方案。
|
4天前
|
Unix Linux Go
go进阶编程:Golang中的文件与文件夹操作指南
本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
|
2月前
|
Go
golang语言之go常用命令
这篇文章列出了常用的Go语言命令,如`go run`、`go install`、`go build`、`go help`、`go get`、`go mod`、`go test`、`go tool`、`go vet`、`go fmt`、`go doc`、`go version`和`go env`,以及它们的基本用法和功能。
42 6
|
5月前
|
Go
golang启动报错【已解决】
golang启动报错【已解决】
40 0
|
5月前
|
Unix Go 调度
【Golang】- runtime.Goexit()
【Golang】- runtime.Goexit()
45 0
|
Go 开发工具 C语言
Golang框架:cobra
这些都是命令,二前面的ls、git、gcc等都是我们写的程序。如果不使用 cobra 框架进行编写这些命令,那么程序写起来是相当费劲的。
107 0
golang go get 时提示 no Go files in xxx
golang go get 时提示 no Go files in xxx
golang go get 时提示 no Go files in xxx
|
Java Linux Go
知识分享之Golang——go get 常用命令
知识分享之Golang篇是我在日常使用Golang时学习到的各种各样的知识的记录,将其整理出来以文章的形式分享给大家,来进行共同学习。欢迎大家进行持续关注。 知识分享系列目前包含Java、Golang、Linux、Docker等等。
258 0
知识分享之Golang——go get 常用命令
|
Java Linux Go
知识分享之Golang——go mod常用命令解析
知识分享之Golang篇是我在日常使用Golang时学习到的各种各样的知识的记录,将其整理出来以文章的形式分享给大家,来进行共同学习。欢迎大家进行持续关注。 知识分享系列目前包含Java、Golang、Linux、Docker等等。
167 0
知识分享之Golang——go mod常用命令解析