database/sql 接口

Go官方没有提供数据库驱动,而是为开发数据库驱动定义了一些标准接口database/sql,开发者可以根据定义的接口来开发相应的数据库驱动,这样做有一个好处,只要是按照标准接口开发的代码, 以后需要迁移数据库时,不需要任何修改。

MySQL

常用的有如下几种:

这里使用go-sql-driver/mysql驱动进行演示,原因是该库使用人数最多,且支持database/sql接口。

示例:

package main

import (
_ "github.com/go-sql-driver/mysql"
"database/sql"
"fmt"
) type User struct {
Id int
Name string
Gender int
Age int
} func checkErr(err error) {
if err != nil {
panic(err)
}
} func main() {
db, err := sql.Open("mysql", "root:@(127.0.0.1:3306)/test?charset=utf8")
checkErr(err) //查询
rows, err := db.Query("SELECT id,name,gender,age from user limit 2")
checkErr(err) var users []User
for rows.Next() {
var u User
rows.Scan(&u.Id, &u.Name, &u.Gender, &u.Age)
users = append(users, u)
} //fmt.Print(users)
for _,u := range users{
fmt.Printf("id:%d, name:%s, gender:%d, age:%d\n", u.Id, u.Name, u.Gender, u.Age)
}
}

输出:

id:1, name:allen, gender:1, age:20
id:2, name:alice, gender:2, age:18

新增:

stmt, err := db.Prepare("INSERT INTO user (name,age) VALUES (?, ?)")
checkErr(err)
res, err := stmt.Exec("golang", 10)
checkErr(err)
fmt.Println(res.LastInsertId())

输出:

26 <nil>

注:res.LastInsertId()返回的新增id和error。

更新:

stmt, err := db.Prepare("update user set age = ? where id = ?")
checkErr(err)
res, err := stmt.Exec(8, 26)
checkErr(err)
fmt.Println(res.RowsAffected())

输出:

1 <nil>

注:res.RowsAffected()返回的影响函数和error。

删除:

stmt, err := db.Prepare("DELETE FROM user where id = ?")
checkErr(err)
res, err := stmt.Exec( 26)
checkErr(err)
fmt.Println(res.RowsAffected()) //或者
//res, err := db.Exec("DELETE FROM user where id = 26")
//checkErr(err)
//fmt.Println(res.RowsAffected())

可以简单封装一下:

func NewMysqlClient() (*sql.DB, error) {
address := "127.0.0.1:3306"
user := "root"
password := ""
database := "test"
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4", user, password, address, database)
db, err := sql.Open("mysql", dsn)
return db, errors.Wrap(err, "can not connect db.")
}

PostgreSQL

常见驱动库:

这里使用lib/pq进行演示,因为该库使用的人数最多。

import (
"database/sql" _ "github.com/lib/pq"
) //获取客户端
func NewPostgreSQLClient() (*sql.DB, error) {
address := "127.0.0.1"
user := "pqgotest"
password := ""
database := "pqgotest"
dsn := fmt.Sprintf("%s://%s:%s@%s/%s?sslmode=verify-full", user, password, address, database)
db, err := sql.Open("postgres", dsn)
return db, errors.Wrap(err, "can not connect db.")
} func main() {
db, err := NewPostgreSQLClient()
if err != nil {
log.Fatal(err)
} age := 21
rows, err := db.Query("SELECT name FROM users WHERE age = $1", age)
//…
}

SQLite

驱动库:https://github.com/mattn/go-sqlite3

该驱动采用database/sql接口,所以使用起来和操作MySQL是一样的。

增删改查示例:

package main

import (
"database/sql"
"fmt" _ "github.com/mattn/go-sqlite3"
) //CREATE TABLE `userinfo` (
// `uid` INTEGER PRIMARY KEY AUTOINCREMENT,
// `username` VARCHAR(64) NULL,
// `departname` VARCHAR(64) NULL,
// `created` DATE NULL
//); func checkErr(err error) {
if err != nil {
panic(err)
}
} type UserInfo struct {
uid int
username string
departname string
created string
} func main() {
db, err := sql.Open("sqlite3", "./test_sqlite.db")
checkErr(err) //增加
stmt, err := db.Prepare("insert into userinfo(username,departname,created) values(?, ?, ?)")
checkErr(err) res, err := stmt.Exec("yjc", "test", "2018-08-12")
checkErr(err) id, err := res.LastInsertId()
checkErr(err) fmt.Println(id) //更新
stmt, err = db.Prepare("update userinfo set username = ? where uid = ?")
checkErr(err) res, err = stmt.Exec("golang", 1)
checkErr(err) affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect) //查询
rows, err := db.Query("select * from userinfo")
checkErr(err) var user UserInfo
var users []UserInfo
for rows.Next() {
rows.Scan(&user.uid, &user.username, &user.departname, &user.created)
users = append(users, user)
} fmt.Println(users) //删除
stmt, err = db.Prepare("delete from userinfo where uid = ?")
checkErr(err) res, err = stmt.Exec(2)
checkErr(err) affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect) }

可以简单封装一下:

func NewSqliteClient() (*sql.DB, error) {
dbname := "./test_sqlite.db"
db, err := sql.Open("sqlite3", dbname)
return db, errors.Wrap(err, "can not connect db.")
}

redis

Go目前支持redis的驱动有如下

前面两个Star数是最多的,生产环境推荐从前面两个选择。使用上go-redis/redis简单些。

go-redis/redis示例

//获取客户端
func NewRedisClient() *redis.Client {
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
}) //pong, err := client.Ping().Result()
//fmt.Println(pong, err)
// Output: PONG <nil>
return client
} //test
func ExampleClient() {
client := NewRedisClient()
defer client.Close() err := client.Set("key", "value", 0).Err()
if err != nil {
panic(err)
} val, err := client.Get("key").Result()
if err != nil {
panic(err)
}
fmt.Println("key", val) val2, err := client.Get("key2").Result()
if err == redis.Nil {
fmt.Println("key2 does not exist")
} else if err != nil {
panic(err)
} else {
fmt.Println("key2", val2)
}
// Output: key value
// key2 does not exist
}

mongoDB

目前Go支持mongoDB最好的驱动就是mgo,地址:http://labix.org/mgo

2019-08-18 更新:很长一段时间,MongoDB 的 Go 语言驱动一直使用的 mgo 这个,但由于作者工作中不再使用 MongoDB,出于精力等方面的考虑,该项目不再维护。而且我们有了官方出品的驱动,自然应该使用它了。地址:https://github.com/mongodb/mongo-go-driver。

安装mgo:

go get gopkg.in/mgo.v2

示例:

package main

import (
"fmt"
"log"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
) type Person struct {
Name string
Phone string
} func main() {
session, err := mgo.Dial("server1.example.com,server2.example.com")
if err != nil {
panic(err)
}
defer session.Close() // Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true) c := session.DB("test").C("people")
err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
log.Fatal(err)
} result := Person{}
err = c.Find(bson.M{"name": "Ale"}).One(&result)
if err != nil {
log.Fatal(err)
} fmt.Println("Phone:", result.Phone)
}

Elasticsearch

常用驱动:

Go如何使用数据库、缓存的更多相关文章

  1. ASP.NET缓存全解析6:数据库缓存依赖 转自网络原文作者李天平

    更多的时候,我们的服务器性能损耗还是在查询数据库的时候,所以对数据库的缓存还是显得特别重要,上面几种方式都可以实现部分数据缓存功能.但问题是我们的数据有时候是在变化的,这样用户可能在缓存期间查询的数据 ...

  2. Apache Ignite——新一代数据库缓存系统

    [编者按]飞速增长的数据需要大量存储,对这些数据的管理也不是一件容易的事.但相比于存储和管理,如何处理数据才是开发人员真正的挑战.对于TB级别数据的存储和处理通常会让开发人员陷入速度.可扩展性和开销的 ...

  3. (转)ASP.NET缓存全解析6:数据库缓存依赖

    ASP.NET缓存全解析文章索引 ASP.NET缓存全解析1:缓存的概述 ASP.NET缓存全解析2:页面输出缓存 ASP.NET缓存全解析3:页面局部缓存 ASP.NET缓存全解析4:应用程序数据缓 ...

  4. 网站优化指南之数据库缓存、CDN与云存储

    1 数据库缓存. 常见的做法是用内存做cache,把数据库里的内容提前取出读到内存里,用户再请求时,就不直接读数据库,而是读内存里的数据,从而缓解了数据库的压力. 过去比较常用的缓存软件是memcac ...

  5. Java数据库缓存思路

    为什么要用缓存?如果问这个问题说明你还是新手,数据库吞吐量毕竟有限,每秒读写5000次了不起了,如果不用缓存,假设一个页面有100个数据库操作,50个用户并发数据库就歇菜,这样最多能支撑的pv也就50 ...

  6. Asp.net数据库缓存依赖

    Asp.net数据库缓存依赖 更多的时候,我们的服务器性能损耗还是在查询数据库的时候,所以对数据库的缓存还是显得特别重要,上面几种方式都可以实现部分数据缓存功能.但问题是我们的数据有时候是在变化的,这 ...

  7. Sql缓存依赖--数据库缓存

    •依赖于文件内容CacheDependency cDep = new CacheDependency(filePath); •依赖于数据库内容(轮询机制/通知机制)一:轮询机制 1.在数据库新建版本表 ...

  8. Django Cache缓存系统学习--数据库缓存

    Django是动态网站,用户每一次请求页面,服务器都会执行以下操作:数据库查询.渲染模版.执行业务逻辑,最后生成用户可查看的页面.当访问量比较大的时候,会消耗掉大量的资源,这时候就会考虑到缓存问题. ...

  9. 用Redis作Mysql数据库缓存

    使用redis作mysql数据库缓存时,需要考虑两个问题: 1.确定用何种数据结构存储来自Mysql的数据; 2.在确定数据结构之后,用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是按 ...

  10. redis(二)--用Redis作MySQL数据库缓存

    用Redis作MySQL数据库缓存,必须解决2个问题.首先,应该确定用何种数据结构存储来自mysql的数据:在确定数据结构之后,还要考虑用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是 ...

随机推荐

  1. 9.第一个vue-cli项目

    1.什么是vue-cli vue-cli 官方提供的一个脚手架,用于快速生成一个 vue 的项目模板; 预先定义好的目录结构及基础代码,就好比咱们在创建 Maven 项目时可以选择创建一个骨架项目,这 ...

  2. Python 包制作

    Python 包制作 官方文档 Python 包目录 /package_parent_folder /package /__init__.py 在__init__.py文件内添加name = pack ...

  3. Linux性能优化实战学习笔记:第二十八讲

    一.案例环境描述 1.环境准备 2CPU,4GB内存 预先安装docker sysstat工具 apt install docker.io sysstat nake git 案例总共由三个容器组成: ...

  4. subprocess实用手册

    背景 python执行操作系统的命令,如python执行shell命令 subprocess模块主要用于创建子进程,并连接它们的输入.输出和错误管道,获取它们的返回状态.通俗地说就是通过这个模块,你可 ...

  5. 如何让position fixed不再基于浏览器窗口定位

    position:fixed默认是相对浏览器定位的. 就是将某个元素固定在浏览器的某个确定的位置,不随滚动条的移动而变化: MDN对position: fixed有一个注释: 当元素祖先的 trans ...

  6. JMM与happens-before

    happens-before是JMM最核心的概念,理解happens-before是理解JMM的关键. 一.JMM的设计 首先,让我们先分析一下JMM的设计意图.从JMM的设计者的角度,在设计JMM的 ...

  7. Vue.js 源码分析(十四) 基础篇 组件 自定义事件详解

    我们在开发组件时有时需要和父组件沟通,此时可以用自定义事件来实现 组件的事件分为自定义事件和原生事件,前者用于子组件给父组件发送消息的,后者用于在组件的根元素上直接监听一个原生事件,区别就是绑定原生事 ...

  8. [转帖]linux下网络监控神器"iptraf-ng"

    linux下网络监控神器"iptraf-ng" https://www.cnblogs.com/dupengfei/articles/iptraf-ng.html 优点:监控的网络 ...

  9. scala中停止循环的三种方式

    1:使用return关键字 object BreakLoop { //1.使用return关键字 def add():Unit= { for(i <- 1 to 10){ if(i==7){ / ...

  10. 2019-11-29-win10-uwp-关联文件

    原文:2019-11-29-win10-uwp-关联文件 title author date CreateTime categories win10 uwp 关联文件 lindexi 2019-11- ...