【轻知识】Go入门学习整理——第五节,数据入mysql、入redis、包管理glide、beego框架略览

mysql

继续上节的代码。上节的代码是把数据存到了数组中。相当于存到了内存中了。现在操作MySQL。添加数据到mysql中,从mysql中查询数据,并删除

一个类库的使用似乎没有什么太难的。

test库yan_user表。

CREATE TABLE `yan_user` (
    `id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(60) NOT NULL DEFAULT '',
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

操作库用这个https://github.com/go-sql-driver/mysql。go get -u github.com/go-sql-driver/mysql。

把添加的名字落入数据库。

db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test")
defer db.Close()
if err != nil {
    panic(err)
}
stmt, err := db.Prepare("INSERT INTO yan_user SET name=?")
if err != nil {
    panic(err)
}
res, err := stmt.Exec(name)
if err != nil {
    panic(err)
}
id, err := res.LastInsertId()
if err != nil {
    panic(err)
}

查询的那块也从mysql中查询。

db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test")
defer db.Close()
if err != nil {
    panic(err)
}
rows, err := db.Query("SELECt * FROM yan_user")
if err != nil {
    panic(err)
}
var nameList []map[string]interface{}
for rows.Next() {
    var id int
    var name string
    err = rows.Scan(&id, &name)
    if err != nil {
        panic(err)
    }
    nameList = append(nameList, map[string]interface{}{"id": id, "name": name})
}

redis

类库使用的是https://github.com/go-redis/redis

go get -u github.com/go-redis/redis

在添加名字,名字入库的时候,把id 跟name存入list中。

// 插入到redis中
client := redis.NewClient(&redis.Options{
    Addr:     "x.x.x.x:18000",
    Password: "", // no password set
    DB:       0,  // use default DB
})

pong, err := client.Ping().Result()
fmt.Println(pong, err)
jsonRes, err := json.Marshal(map[string]interface{}{"id": id, "name": name})
if err != nil {
    panic(err)
}
client.LPush("name_list", jsonRes)

然后再写一个接口是从redis查出来的数据。

http.HandleFunc("/search_from_redis", func(w http.ResponseWriter, r *http.Request) {
    // 插入到redis中
    client := redis.NewClient(&redis.Options{
        Addr:     "x0.x0.xx.15:18000",
        Password: "", // no password set
        DB:       0,  // use default DB
    })

    pong, err := client.Ping().Result()
    fmt.Println(pong, err)
    res, err := client.LRange(nameListKey, 0, 100).Result()

    if err != nil {
        panic(err)
    }
    type Name struct {
        Id   int    `json:"id"`
        Name string `json:"name"`
    }
    var name Name
    var nameList []Name
    for _, value := range res {
        json.Unmarshal([]byte(value), &name)
        nameList = append(nameList, name)
    }
    data := map[string]interface{}{"name_list": nameList}
    list, err := json.Marshal(data)
    if err != nil {
        fmt.Println("json.Marshal failed:", err)
        return
    }
    w.Header().Add("Content-Type", "application/json")
    fmt.Fprintf(w, string(list)) //这个写入到w的是输出到客户端的
})

界面如下

image.png

包管理工具

上面我们go get了mysql 跟redis 的库。这个库放到了我配置的第一个gopath下面了。

vendor目录。

现在我在代码中import里面引入一个随便写的类库github.com\go-d。编辑器就会告诉你没有在gopath中找到。如果在src下面创建了一个vendor目录,报错信息的第一条就是vendor下面没有这个库。

vendor是1.5版本后加的。查找依赖包的解决方案如下(摘自极客时间):

1.当前包下的vendor目录

2.向上级目录查找,直到找到src下的vendor 目录

3.在GOPATH下面查找依赖包

4.在GOROOT目录下查找

但你看控制台从报错信息中就能看出规律。如下是我的:

cannot find package "github.com/go-d" in any of:
    F:\iProject\xiaotianquan\src\vendor\github.com\go-d (vendor tree)
    C:\Go\src\github.com\go-d (from $GOROOT)
    F:\iProject\gopath\src\github.com\go-d (from $GOPATH)
    F:\iProject\xiaotianquan\src\github.com\go-d

依赖管理的工具有好几个。文末参考资料中自行了解。

glide

安装方式去官方文档

windows的话,因为我安装过gitbash,所以在gitbash中执行curl https://glide.sh/get | sh也就安装好了(安装到了go/bin目录下了)。(但我的版本有问题,下面会说到。不得不去github上找低版本的https://github.com/Masterminds/glide/releases

我在之前的代码中又拷贝了一份目录(web3)。在main.go(我demo的文件)同级目录下。我执行glide init ,看到了glide.yaml文件,文件的内容。

package: web3
import:
- package: github.com/go-redis/redis
  version: v6.15.2
- package: github.com/go-sql-driver/mysql
  version: v1.4.1

是不是有种composer的感觉。

执行glide ,会在我web3(web3在src目录下)的目录下生成一个vendor目录(而不是在src)。那么下次引入其他的类库会在这个vendor里面找。

但使用的过程中报错了。我找到了一条issuehttps://github.com/Masterminds/glide/issues/873。应该该版本在windows下的问题。我安装的版本是glide version v0.13.2。有人说这个版本0.12.3有效。

Unable to export dependencies to vendor directory: Error moving files: exit status 1. output: Access is denied.
        0 dir(s) moved.

0.12.3 确实可以。我把下载glide 放到了go/bin下面替换了之前安装的版本。

然后执行glide install。vendor目录下就有了相关的类库了。这样以后依赖管理就方便了。我的包也不用去都放到一个gopath下了(甚至就放到我的项目目录下的vendor里面)。

更多使用glide版本管理的方式。请看官网:https://glide.readthedocs.io

beego框架略览

到现在细数下做到的功能。

1.模板渲染
2.mysql操作
3.redis操作
4.json操作
5.版本管理(glide)

OK,到现在我们已经具备了CURD的能力(虽然我没有写D跟U的代码)。来看一个框架beego。有人说这是go的ThinkPHP。

安装bee工具。go get github.com/beego/bee。

我拷贝一个文件夹起名为web4。进入其目录。创建一个项目bee new myproject

cd myproject,执行 bee run。提示我main.go:5:2: cannot find package "github.com/astaxie/beego。OK,没关系。我开始安装下beego。这次就用glide去管理吧。

在myproject 执行glide init。然后glide install。

OK,bee run执行(由于我本地装了Jenkins,我需要到conf/app.conf改成其他端口,比如8081吧)

OK,http://127.0.0.1:8081/ 你看到了Welcome to Beego

beego 版 名单

controllers下面我们新建一个name.go。我就把整个代码贴下去了哈。

package controllers

import (
    "encoding/json"
    "fmt"
    "github.com/astaxie/beego"
    "github.com/astaxie/beego/orm"
    "github.com/gomodule/redigo/redis"
)

type NameController struct {
    beego.Controller
}

func (c *NameController) Get() {
    c.Data["Website"] = "beego.me"
    c.Data["Email"] = "astaxie@gmail.com"

    c.TplName = "name/index.tpl"
}
func (c *NameController) Add() {
    name := c.Input().Get("name")

    o := orm.NewOrm()

    r := o.Raw("INSERT INTO yan_user SET name=?", name)
    res, err := r.Exec()
    if err != nil {
        panic(err)
    }
    id, err := res.LastInsertId()
    if err != nil {
        panic(err)
    }
    c.Data["json"] = &id
    conn, err := redis.Dial("tcp", "xx.x0.x.x5:18000")
    if err != nil {
        panic(err)
    }
    defer conn.Close()
    jsonRes, err := json.Marshal(map[string]interface{}{"id": id, "name": name})
    if err != nil {
        panic(err)
    }
    conn.Do("lpush", "name_list", jsonRes)
    c.ServeJSON()
}
func (c *NameController) Search() {
    type Name struct {
        Id   int    `json:"id"`
        Name string `json:"name"`
    }
    var nameList []Name

    o := orm.NewOrm()
    num, err := o.Raw("SELECT * FROM yan_user").QueryRows(&nameList)
    if err != nil {
        panic(err)
    }
    fmt.Println("user nums: ", num)
    data := map[string][]Name{"name_list": nameList}
    c.Data["json"] = &data
    c.ServeJSON()
}
func (c *NameController) SearchFromRedis() {
    conn, err := redis.Dial("tcp", "xx.xx.x.xx:18000")
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    res, err := redis.Values(conn.Do("lrange", "name_list",0 ,100))


    if err != nil {
        panic(err)
    }

    type Name struct {
        Id   int    `json:"id"`
        Name string `json:"name"`
    }
    var name Name
    var nameList []Name
    for _, value := range res {
        json.Unmarshal(value.([]byte), &name)
        nameList = append(nameList, name)
    }
    data := map[string]interface{}{"name_list": nameList}
    if err != nil {
        fmt.Println("json.Marshal failed:", err)
        return
    }
    c.Data["json"] = &data
    c.ServeJSON()
}

配置路由

beego.Router("/", &controllers.MainController{})
beego.Router("/name/index", &controllers.NameController{})
beego.Router("/name/add", &controllers.NameController{},"post:Add")
beego.Router("/name/search", &controllers.NameController{},"post:Search")
beego.Router("/name/search_from_redis", &controllers.NameController{},"post:SearchFromRedis")

初始化的一些配置。在入口main.go,需要做下面的事情。

  • 指定数据库 (一定别忘了指定数据库驱动github.com/go-sql-driver/mysql,不引入会报register dbdefault, sql: unknown driver "mysql" (forgotten import?)
  • 模板解析的左右标签改下(因为会跟vue冲突)
package main

import (
    _ "web4/myproject/routers"

    "github.com/astaxie/beego"
    _ "github.com/go-sql-driver/mysql"
    "github.com/astaxie/beego/orm"
)

func init() {
    orm.RegisterDriver("mysql", orm.DRMySQL)

    orm.RegisterDataBase("default", "mysql", "root:root@/test?charset=utf8")
    
}

func main() {
    beego.BConfig.WebConfig.TemplateLeft = "<<<"
    beego.BConfig.WebConfig.TemplateLeft = ">>>"
    beego.Run()
}

文档中redis 缓存

使用缓存别忘下载对应的文件。

glide get  github.com/astaxie/beego/cache

glide get github.com/gomodule/redigo/redis

用法,头部先引入

"github.com/astaxie/beego/cache"
_ "github.com/astaxie/beego/cache/redis"
bm, err := cache.NewCache("redis", `{"conn":"xx.x.x.x:18000"}`)
if err != nil {
    panic(err)
}
timeoutDuration := 100 * time.Second // 当然这里还需要引入time包。
err = bm.Put("aaaa", "2222", timeoutDuration)

看下配置

{"key":"collectionName","conn":":6039","dbNum":"0","password":"thePassWord"}

文档中说是key: Redis collection 的名称。没搞明白是啥意思。追了下代码,看明白了。这个key就是前缀。比如你想在代码中Put("name","xiaoming", 100 * time.Second),实际上key如果你不指定默认就是beecacheRedis:name。如果你指定了就是key:name。如果指定的key为空字符串。那么就是:name(不会因为你填的空白字符串,而把冒号去掉。)。所以当你纠结在中断找不get的不到的时候,别忘了前缀哈。

key的拼接在./github.com/astaxie/beego/cache/redis/redis.go中。如下:

func (rc *Cache) associate(originKey interface{}) string {
    return fmt.Sprintf("%s:%s", rc.key, originKey)
}

由于Cache 封装的方法太少。我想用redis list 的功能,只能直接用redigo方法了(代码参考上面的name.go代码)。

总结

这里没有提及到orm的使用。实际上,参考文档就会马上完成用orm的方式。

参考资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354