赞
踩
本文不同于其他Go语言学习的文章,将以项目开发所需为基础,带你飞速踏入Go的世界,成为能独挡一面的强者。当你稍微花几分钟的时间,看完本文的时候,或许你会发现,驾驭Go语言为己所用是如此简单。
山不在高,有仙则名,水不在深,有龙则灵,文不在多,一篇足以。希望我这些小小的经验和用心的分享,能真的帮助到您。
Go 即Golang,是Google公司2009年11月正式对外公开的一门编程语言。
Go是静态强类型语言,是区别于解析型语言的编译型语言。
解析型语言——源代码是先翻译为中间代码,然后由解析器对代码进行解释执行。
编译型语言——源代码编译生成机器语言,然后由机器直接执行机器码即可执行。
所以能看到这些领域都在使用Go语言:微服务开发模式,api开发,rpc服务开发,游戏服务开发等等
Go的开发框架比较多,比较知名的几个分别是Gin、BeeGo、Irir、Echo、Revel、Buffalo。对比排名详见: 《Go语言Web框架对比》
框架的选择上,本人主要遵循如下几点原则,分别是:
选择过程不多说,本人最终选择了beego作为本次入手的框架,本文余下内容如无特别说明,均基于此框架。
安装包下载地址为:https://golang.org/dl/
如果打不开可以使用这个地址:https://golang.google.cn/dl/
【UNIX/Linux/Mac OS X, 和 FreeBSD 安装】
tar -C /usr/local -xzf go1.12.7.linux-amd64.tar.gzexport PATH=$PATH:/usr/local/go/bin注意:MAC 系统下你可以使用 .pkg 结尾的安装包直接双击来完成安装,安装目录在 /usr/local/go/ 下。
本文余下内容如无特别说明,均默认Linux环境
【Windows 系统下安装】
Windows 下可以使用 .msi 后缀(在下载列表中可以找到该文件,如go1.12.7.windows-amd64.msi)的安装包来安装。
默认情况下.msi文件会安装在 c:Go 目录下。你可以将 c:Gobin 目录添加到 PATH 环境变量中。
添加后你需要重启命令窗口才能生效。
安装测试:
创建工作目录 C:>Go_WorkSpace。
- //test.go 文件代码:
- package main
-
- import "fmt"
-
- func main() {
- fmt.Println("Hello, World!")
- }
使用 go 命令执行以上代码输出结果如下:
- C:Go_WorkSpace>go run test.go
-
- Hello, World!
如下环境变量,都是Go编译和运行时必要的,如果安装时没有自动设置好,请务必自己手动添加。
添加环境变量方法:
~/.bashrc文件里(对当前用户有效,首次添加后记得source ~/.bashrc一下)- export GOPATH=~/go
- export GOROOT=/usr/local/go
【安装】
安装方式非常简单,只要敲击如下命令即可(bee工具可以快速创建项目和自动监测运行,记得要安装哦):
- go get github.com/astaxie/beego
- # bee 工具
- go get github.com/beego/bee
安装完之后,bee 可执行文件默认存放在$GOPATH/bin里面,所以您需要把$GOPATH/bin添加到您的环境变量PATH中:export PATH=$PATH:$GOPATH/bin
常见问题:
git config --global http.sslVerify false【创建项目】
打开终端,进入 $GOPATH/src 所在的目录,用bee工具创建一个项目:bee new firstPro
【目录结构】
这是一个典型的 MVC 架构的应用,main.go 是入口文件。目录结构如下所示:
- .
- ├── conf
- │ └── app.conf
- ├── controllers
- │ └── default.go
- ├── main.go
- ├── models
- ├── routers
- │ └── router.go
- ├── static
- │ ├── css
- │ ├── img
- │ └── js
- │ └── reload.min.js
- ├── tests
- │ └── default_test.go
- └── views
- └── index.tpl
-
- 10 directories, 7 files

【编译运行】cd $GOPATH/src/firstPro进入我们创建的项目,使用 bee run 来运行该项目,这样我们的应用就在 8080 端口(beego 的默认端口)跑起来了,让我们打开浏览器看看效果吧:
Go指令
go getgo buildgo runBee工具
bee api 或 bee new 分别创建 api应用 和 web项目,位于 $GOPATH/src 目录下bee run 该命令必须在 $GOPATH/src/appname 下执行bee pack 以上是一些常用的命令,介绍虽比较简单,但只要大概记住他的作用即可。
没有把所有指令都列出来,因为我们暂时还用不到,这些已经足够我们摆平项目的开发了,其他的指令和高级用法,有兴趣的小伙伴们可以动动手自行查阅。
Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
【声明变量】
var name type var name1, name2 type name := value 【零值】
指定变量类型,如果没有初始化,则变量默认为零值。
- var a *int
- var a []int
- var a map[string] int
- var a chan int
- var a func(string) int
- var a error // error 是接口
【示例】
- package main
- import "fmt"
- func main() {
- var a string = "yisonli"
- fmt.Println(a)
-
- var b, c int = 1, 2
- fmt.Println(b, c)
-
- d := []int{10,9,8,7}
- fmt.Println(d)
-
- var e = map[string]int{"one":1, "two":2}
- fmt.Println(e)
- }
以上示例输出结果为:
- yisonli
- 1 2
- [10 9 8 7]
- map[one:1 two:2]
| 类型 | 描述 | | :-- | :-- | | 布尔型 | 布尔型的值只可以是常量 true 或者 false
一个简单的例子:var b bool = true | | 数字类型 | 有符号整型: int、int8、int16、int32、int64 无符号整型: uint、uint8、uint16、uint32、uint64 浮点型: float32、float64 复数: complex64、complex128 其他: byte (类似uint8)、uintptr (存指针)、rune (类似int32) | | 字符串类型 | 一串固定长度的字符连接起来的字符序列,使用 UTF-8 编码标识 Unicode 文本 | | 派生类型 | 包括:
(a) 指针类型(Pointer)
(b) 数组类型
(c) 结构化类型(struct)
(d) Channel 类型
(e) 函数类型
(f) 切片类型
(g) 接口类型(interface)
(h) Map 类型
|
Go 语言函数定义格式如下:
- func function_name( [parameter list] ) [return_types] {
- 函数体
- }
函数定义解析:
【示例】
- package main
-
- import "fmt"
-
- func swap(x, y string) (string, string) {
- return y, x
- }
-
- func main() {
- a, b := swap("Golang", "yisonli")
- fmt.Println(a, b)
- }
以上示例输出结果为:
yisonli Golang
for循环是一个循环控制结构,可以执行指定次数的循环。Go语言的For循环有3种形式,具体定义如下:
- // 1. 类似 C 语言的 for
- for init; condition; post { }
-
- // 2. 类似 C 的 while
- for condition { }
-
- // 3. 类似 C 的 for(;;)
- for { }
【示例】
- package main
-
- import "fmt"
-
- func main() {
-
- var b int = 7
- var a int
-
- numbers := [6]int{1, 2, 3, 5}
-
- /* for 循环 */
- for a := 0; a < 5; a++ {
- fmt.Printf("a 的值为: %dn", a)
- }
-
- for a < b {
- a++
- fmt.Printf("a 的值为: %dn", a)
- }
-
- for i,x:= range numbers {
- fmt.Printf("第 %d 位 x 的值 = %dn", i,x)
- }
- }

以上示例输出结果为:
- a 的值为: 0
- a 的值为: 1
- a 的值为: 2
- a 的值为: 3
- a 的值为: 4
- a 的值为: 1
- a 的值为: 2
- a 的值为: 3
- a 的值为: 4
- a 的值为: 5
- a 的值为: 6
- a 的值为: 7
- 第 0 位 x 的值 = 1
- 第 1 位 x 的值 = 2
- 第 2 位 x 的值 = 3
- 第 3 位 x 的值 = 5
- 第 4 位 x 的值 = 0
- 第 5 位 x 的值 = 0

| 语句 | 描述 | | --- | --- | | if 语句 | if 语句 由一个布尔表达式后紧跟一个或多个语句组成。 | | if...else 语句 | if 语句 后可以使用可选的 else 语句,
else 语句中的表达式在布尔表达式为 false 时执行。 | | if 嵌套语句 | 你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句。 | | switch 语句 | switch 语句用于基于不同条件执行不同动作。 | | select 语句 | select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。
如果没有case可运行,它将阻塞,直到有case可运行。 |
注意:Go 没有三目运算符,所以不支持 ?: 形式的条件判断。
【示例】
- package main
-
- import "fmt"
-
- func main() {
- /* 局部变量定义 */
- var a int = 100;
-
- /* 判断布尔表达式 */
- if a < 20 {
- /* 如果条件为 true 则执行以下语句 */
- fmt.Printf("a 小于 20n" );
- } else {
- /* 如果条件为 false 则执行以下语句 */
- fmt.Printf("a 不小于 20n" );
- }
- fmt.Printf("a 的值为 : %dn", a);
-
- }

以上示例输出结果为:
- a 不小于 20
- a 的值为 : 100
【包的定义和特性】:
.go 为扩展名的源文件组成package mainmain 的包import 关键字可以将一组包链接在一起,在你的应用中导入后方可使用【注意事项】:
imported and not used: os,这正是遵循了 Go 的格言:“没有不必要的代码!“。 public);private )。【普通类型转换】
type_name(expression)
其中type_name 为类型,expression 为表达式。
【格式化输出】
格式化在逻辑中非常常用。使用格式化函数,要注意写法:
fmt.Sprintf(格式化样式, 参数列表…)
【json转换】
这里说的json其实是json格式的string字符串类型,通常json需要转换成struct结构体、或者转换成map映射,正向转换和反向转换其实会经常用到。
在此,我们需要借助Go的标准库 "encoding/json" 来帮我们完成转换的操作了。
- // struct或map 转成 json字符串
- str, err := json.Marshal(object)
-
- // json字符串 转成 struct或map
- err := json.Unmarshal([]byte(str), &object)
扩展:网上有些Go的开发小伙伴们在抱怨说标准库的json效率比较低,而且有几个不错的开源json库可以提升2-3倍的转换性能。该如何取舍就全凭个人喜好了,有兴趣的小伙伴们可以自行去深入了解,本文就不再展开了。
【示例】
- package main
- import (
- "encoding/json"
- "fmt"
- )
- func main () {
- // 1. 普通类型转换
- var sum int = 17
- var count int = 5
- var mean float32
-
- mean = float32(sum)/float32(count)
- fmt.Printf("mean 的值为: %fn",mean)
- fmt.Println()
-
- // 2. 格式化
- title := fmt.Sprintf("已采集%d个药草, 还需要%d个完成任务。", sum, count)
- fmt.Println(title)
- fmt.Println()
-
- // 3. json字符串 转成 struct或map
- var jsonBlob = [] byte (`[
- { "Name" : "Platypus" , "Order" : "Monotremata" } ,
- { "Name" : "Quoll" , "Order" : "Dasyuromorphia" }
- ]`)
- type Animal struct {
- Name string
- Order string
- }
- var animals [] Animal
- err := json.Unmarshal(jsonBlob, &animals)
- if err != nil {
- fmt.Println("error:", err)
- }
- fmt.Printf("%+vn", animals)
-
- var animalsMap []map[string]interface{}
- err1 := json.Unmarshal(jsonBlob, &animalsMap)
- if err1 != nil {
- fmt.Println("error:", err1)
- }
- fmt.Printf("%+vn", animalsMap)
- fmt.Println()
-
- // 4. struct或map 转成 json字符串
- type ColorGroup struct {
- ID int
- Name string
- Colors [] string
- }
- group := ColorGroup {
- ID : 1 ,
- Name : "Reds" ,
- Colors : [] string {"Crimson", "Red", "Ruby", "Maroon"} ,
- }
- groupStr , err2 := json.Marshal(group)
- if err2 != nil {
- fmt.Println("error:", err2)
- }
- fmt.Printf("%sn", groupStr)
-
- var groupMap = map[string]interface{} {"ID":1,"Name":"Reds","Colors":[] string {"Crimson", "Red", "Ruby", "Maroon"}}
- groupStr1 , err3 := json.Marshal(groupMap)
- if err3 != nil {
- fmt.Println("error:", err3)
- }
- fmt.Printf("%sn", groupStr1)
- }

以上示例输出结果为:
- mean 的值为: 3.400000
-
- 已采集17个药草, 还需要5个完成任务。
-
- [{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]
- [map[Name:Platypus Order:Monotremata] map[Name:Quoll Order:Dasyuromorphia]]
-
- {"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]}
- {"Colors":["Crimson","Red","Ruby","Maroon"],"ID":1,"Name":"Reds"}
根据项目难易程度,需要掌握的技术知识点会有所不同;本文会根据项目中常用的、基础的、必须掌握的功能点,逐个进行讲解和示例,希望我这些小小的经验和用心的分享,能真的帮助到你,让你在Go的世界里翱翔。
_ "firstPro/routers"beego.Router("/", &controllers.MainController{})BeeGo支持的路由配置方式有很多,但正因为多所以短时间理解起来会比较难,所以这里只列出了大致的分类,以及最为基本的配置方式。先把简单的理解了,如果个人确实有额外特殊的需求,再另行深入,也会清晰得多。
【基础路由】
普通的Get和Post,参见如下代码:
- beego.Get("/",func(ctx *context.Context){
- ctx.Output.Body([]byte("this is get"))
- })
-
- beego.Post("/save",func(ctx *context.Context){
- ctx.Output.Body([]byte("this is post"))
- })
【RESTful路由】
- // 全匹配, 自动找Controller内对应REST的方法
- beego.Router("/", &controllers.MainController{})
-
- // 自定义规则, 第三个参数就是用来设置对应 method 到函数名
- beego.Router("/api/list",&RestController{},"*:List")
- beego.Router("/api/create",&RestController{},"post:Create")
【注解路由】
用户无需在 router 中注册路由,只需要 Include 相应地 controller,然后在 controller 的 method 方法上面写上 router 注释(// @router)就可以了。
- func init() {
- ns :=
- beego.NewNamespace("/v1",
- beego.NSNamespace("/customer",
- beego.NSInclude(
- &controllers.CustomerController{},
- &controllers.CustomerCookieCheckerController{},
- ),
- ),
- beego.NSNamespace("/cms",
- beego.NSInclude(
- &controllers.CMSController{},
- ),
- ),
- )
- beego.AddNamespace(ns)
- }

注意:为了生成swagger自动化文档,只支持 Namespace+Include 写法的解析,其他写法函数不会自动解析,而且只支持二级解析(一级版本号,二级分别表示应用模块)
【参数获取】
我们经常需要获取用户传递的数据,包括 Get、POST 等方式的请求,beego 里面会自动解析这些数据,你可以通过如下方式获取数据:
- GetString(key string) string
- GetStrings(key string) []string
- GetInt(key string) (int64, error)
- GetBool(key string) (bool, error)
- GetFloat(key string) (float64, error)
【解析到Struct】
适用于Form表单提交的形式,使用方法也很简单,先定义个结构体,然后调用 this.ParseForm(结构体指针) 即可。
注意:
【原始请求数据】
app.conf 里设置 copyrequestbody = truethis.Ctx.Input.RequestBody 获取
更多其他的 request 的信息,用户可以通过
this.Ctx.Request 获取
【json参数返回】
在 Controller 中给 this.Data["json"] 赋值, 然后调用 this.ServeJSON() 即可
【示例】
- package controllers
-
- import (
- "github.com/astaxie/beego"
- "fmt"
- )
-
- type MainController struct {
- beego.Controller
- }
-
- type user struct {
- Id int `form:"-"`
- Name interface{} `form:"username"`
- Age int `form:"age"`
- Email string
- }
-
- func (this *MainController) Post() {
- email := this.GetString("Email")
- fmt.Println(email)
-
- body := this.Ctx.Input.RequestBody
- fmt.Printf("%sn", string(body))
-
- u := user{}
- if err := this.ParseForm(&u); err != nil {
- //handle error
- this.Data["json"] = map[string]interface{}{"code":-1, "message":"ParseForm fail", "result":err}
- } else {
- fmt.Printf("%+vn", u)
- this.Data["json"] = map[string]interface{}{"code":0, "message":"ok"}
- }
- this.ServeJSON()
- this.StopRun()
- }

以上示例控制台结果为:
- // 模拟请求:curl -X POST -d "username=yisonli&age=18&Email=yisonli@vip.qq.com" "http://127.0.0.1:8080"
- yisonli@vip.qq.com
- username=yisonli&age=18&Email=yisonli@vip.qq.com
- {Id:0 Name:yisonli Age:18 Email:yisonli@vip.qq.com}
使用数据库前需先装好数据库驱动,其实只要执行 go get -u 指令即可。
已支持数据库驱动:
【连接数据库】
1. 将你需要使用的 driver 加入 import 中
- import (
- _ "github.com/go-sql-driver/mysql"
- _ "github.com/lib/pq"
- _ "github.com/mattn/go-sqlite3"
- )
按个人项目需求来选择即可,本文将以mysql为例进行演示和说明
- orm.RegisterDriver("mysql", orm.DRMySQL)
-
- orm.RegisterDataBase("default", "mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&loc=Local")
注:
1. loc=Local 是将操作数据库的时区,设置成跟本地时区一样。
2. 如果你想像我一样,在本机运行mysql的服务端,而你又恰好装了Docker,那么恭喜你,只需要一条指令启动docker镜像即可:docker run --name mysqlserver -e MYSQL_ROOT_PASSWORD=123456 -d -i -p 3306:3306 mysql:5.7
【原生CRUD】
- package controllers
-
- import (
- "github.com/astaxie/beego"
- "github.com/astaxie/beego/orm"
- _ "github.com/go-sql-driver/mysql"
- "fmt"
- )
-
- type TestController struct {
- beego.Controller
- }
-
- func (this *TestController) Get() {
- orm.RegisterDriver("mysql", orm.DRMySQL)
- orm.RegisterDataBase("default", "mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&loc=Local")
-
- orm.Debug = true //是否开启sql调试,开启时可以打印所有执行的sql语句,不设置时默认为false
- o := orm.NewOrm()
- o.Using("default") //如果连接了多个数据库,此方法可以用来切换,不设置时默认是default的DataBase
-
- var maps []orm.Params
- num1, err1 := o.Raw("SELECT * FROM users").Values(&maps)
- if num1 > 0 && err1 == nil {
- for _,term := range maps{
- fmt.Printf("%+vn",term)
- }
- }
-
- res2, err2 := o.Raw("INSERT INTO `users` (`name`, `age`, `email`) VALUES ('Test', 27, 'test@gmail.com')").Exec();
- if err2 == nil {
- num2, _ := res2.RowsAffected()
- fmt.Println("mysql row affected nums: ", num2)
- }
-
- res3, err3 := o.Raw("UPDATE `users` SET `age`=18 WHERE `name`='Test'").Exec()
- if err3 == nil {
- num3, _ := res3.RowsAffected()
- fmt.Println("mysql row affected nums: ", num3)
- }
-
- res4, err4 := o.Raw("DELETE FROM `users` WHERE `name`='Test'").Exec()
- if err4 == nil {
- num4, _ := res4.RowsAffected()
- fmt.Println("mysql row affected nums: ", num4)
- }
-
- this.Data["json"] = map[string]interface{}{"code":0, "message":"ok"}
- this.ServeJSON()
- }

运行结果:
- [ORM]2019/07/17 15:30:51 -[Queries/default] - [ OK / db.Query / 0.9ms] - [SELECT * FROM users]
- map[email:Lily@qq.com id:1 name:Lily age:18]
- map[id:2 name:Lucy age:20 email:Lucy@gmail.com]
- map[email:Honey@foxmail.com id:3 name:Honey age:30]
- [ORM]2019/07/17 15:30:51 -[Queries/default] - [ OK / db.Exec / 6.9ms] - [INSERT INTO `users` (`name`, `age`, `email`) VALUES ('Test', 27, 'test@gmail.com')]
- mysql row affected nums: 1
- [ORM]2019/07/17 15:30:51 -[Queries/default] - [ OK / db.Exec / 3.1ms] - [UPDATE `users` SET `age`=18 WHERE `name`='Test']
- mysql row affected nums: 1
- [ORM]2019/07/17 15:30:51 -[Queries/default] - [ OK / db.Exec / 6.4ms] - [DELETE FROM `users` WHERE `name`='Test']
- mysql row affected nums: 1
- 2019/07/17 15:30:51.054 [D] [server.go:2741] | 127.0.0.1| 200 | 28.352094ms| match| GET /test/ r:/test
【ORM】
ORM是一个比较强大的功能,他可以让我们的表结构,通过Struct定义的方式表现&关联起来,方便使用。
目前该框架仍处于开发阶段,让我们来看看官网的示例吧:
models.go
- package main
-
- import (
- "github.com/astaxie/beego/orm"
- )
-
- type User struct {
- Id int
- Name string
- Profile *Profile `orm:"rel(one)"` // OneToOne relation
- Post []*Post `orm:"reverse(many)"` // 设置一对多的反向关系
- }
-
- type Profile struct {
- Id int
- Age int16
- User *User `orm:"reverse(one)"` // 设置一对一反向关系(可选)
- }
-
- type Post struct {
- Id int
- Title string
- User *User `orm:"rel(fk)"` //设置一对多关系
- Tags []*Tag `orm:"rel(m2m)"`
- }
-
- type Tag struct {
- Id int
- Name string
- Posts []*Post `orm:"reverse(many)"`
- }
-
- func init() {
- // 需要在init中注册定义的model
- orm.RegisterModel(new(User), new(Post), new(Profile), new(Tag))
- }

main.go
- package main
-
- import (
- "fmt"
- "github.com/astaxie/beego/orm"
- _ "github.com/go-sql-driver/mysql"
- )
-
- func init() {
- orm.RegisterDriver("mysql", orm.DRMySQL)
-
- orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8")
- }
-
- func main() {
- o := orm.NewOrm()
- o.Using("default") // 默认使用 default,你可以指定为其他数据库
-
- profile := new(Profile)
- profile.Age = 30
-
- user := new(User)
- user.Profile = profile
- user.Name = "slene"
-
- fmt.Println(o.Insert(profile))
- fmt.Println(o.Insert(user))
- }

BeeGo还封装了很多高级的查询方法,有兴趣的小伙伴可以额外深入了解一下;因为篇幅有限,这里就不再展开了。
httplib 库主要用来模拟客户端发送 HTTP 请求,类似于 Curl 工具,支持 JQuery 类似的链式操作。
- // 首先导入包
- import (
- "github.com/astaxie/beego/httplib"
- )
-
- // 然后初始化请求方法,返回对象
- req := httplib.Get("http://yyeer.com/")
-
- // 超时时间、Header头都可以按需设置
- req.SetTimeout(100 * time.Second, 30 * time.Second)
- req.Header("Host","yyeer.com")
-
- // 然后我们就可以获取数据了
- str, err := req.String()
- if err != nil {
- fmt.Println(err)
- }
- fmt.Println(str)

【支持的方法对象】
【获取返回结果】
req.Response() 方法req.Bytes() 方法req.String() 方法req.ToFile(filename) 方法req.ToJSON(&result) 方法req.ToXml(&result) 方法BeeGo框架内自动集成了swagger模块,要使得文档工作,你需要做几个事情,
EnableDocs = true,_ "beeapi/docs"(beego 1.7.0 之后版本不需要添加该引用)。bee run -gendoc=true -downdoc=true, 让我们的 API 应用跑起来【全局注释】
必须设置在 routers/router.go 中,文件的注释,最顶部:
- // @APIVersion 1.0.0
- // @Title mobile API
- // @Description mobile has every tool to get any job done, so codename for the new mobile APIs.
- // @Contact astaxie@gmail.com
- package routers
全局的注释如上所示,是显示给全局应用的设置信息,有如下这些设置
【应用注释】
- // CMS API
- type CMSController struct {
- beego.Controller
- }
-
- // @Title getStaticBlock
- // @Description get all the staticblock by key
- // @Param key path string true "The email for login"
- // @Success 200 {object} models.ZDTCustomer.Customer
- // @Failure 400 Invalid email supplied
- // @Failure 404 User not found
- // @router /staticblock/:key [get]
- func (c *CMSController) StaticBlock() {
-
- }
首先是 CMSController 定义上面的注释,这个是用来显示这个模块的作用。
接下来就是每一个函数上面的注释,这里列出来支持的各种注释:
formData、query、path、body、header,formData 表示是 post 请求的数据,query 表示带在 url 之后的参数,path 表示请求路径上得参数,例如上面例子里面的 key,body 表示是一个 raw 数据请求,header 表示带在 header 信息中得参数。【常规使用】
首先引入包:
- import (
- "github.com/astaxie/beego/logs"
- )
然后添加输出引擎:
logs.SetLogger("console")``go logs.SetLogger(logs.AdapterFile,{"filename":"project.log","level":7,"maxlines":0,"maxsize":0,"daily":true,"maxdays":10,"color":true}`)- > log 支持同时输出到多个引擎,包括:console、file、conn、smtp、es、multifile
-
- 使用方式:
-
- ```go
- beego.Emergency("this is emergency")
- beego.Alert("this is alert")
- beego.Critical("this is critical")
- beego.Error("this is error")
- beego.Warning("this is warning")
- beego.Notice("this is notice")
- beego.Informational("this is informational")
- beego.Debug("this is debug")
【自定义格式】
如果框架自带的日志功能还无法满足你的需求,那可能就得麻烦一点,自定义日志格式。
操作流程大致为:
os.OpenFilelog.NewPrintf- File, err := os.OpenFile(logdir, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
- if nil != err {
- log.Fatal(err)
- }
- MyLog = log.New(io.MultiWriter(File,os.Stderr), "", 0)
-
- MyLog.Printf("自己定义的格式... %sn", 自己定义的参数, fmt.Sprintf(formating, args...))
实际使用时, 可以把
MyLog.Printf 封装成一个全局方法,这样整个项目里都可使用。
加解密在多方对接的时候,经常会用到,所以稍微了解一点也是必要的。
因为这块使用的人比较多,所以只要肯稍微花点时间,在网上都是可以找到答案的。
【MD5】
MD5主要是用作签名,具体生成方法如下:
- import (
- "crypto/md5"
- "encoding/hex"
- )
-
- func MyMd5(Str string, Key string) string {
- md5ctx := md5.New()
- md5ctx.Write([]byte(Str + Key))
- return hex.EncodeToString(md5ctx.Sum(nil))
- }
【AES】
AES主要是用作加解密,还分好几种不同的模式如:ECB、CBC、CFB等。
网上找到一份看起来还不错的《AES的加解密实现》,原谅我的小偷懒(还没有在实际项目验证过),God Bless。
其他还有SHA、DES、RSA等加解密方式,具体就得根据各小伙伴不同项目所需了。
Go Go Go !去吧,你可以的!
- // 首先引入包:
- import (
- "github.com/astaxie/beego/cache"
- )
-
- // 然后初始化一个全局变量对象:
- bm, err := cache.NewCache("memory", `{"interval":60}`)
-
- // 然后我们就可以使用bm增删改缓存:
- bm.Put("astaxie", 1, 10*time.Second)
- bm.Get("astaxie")
- bm.IsExist("astaxie")
- bm.Delete("astaxie")
【配置说明】
{"interval":60}{"CachePath":"./cache","FileSuffix":".cache","DirectoryLevel":"2","EmbedExpiry":"120"}{"key":"collectionName","conn":":6039","dbNum":"0","password":"thePassWord"}
key: Redis collection 的名称conn: Redis 连接信息dbNum: 连接 Redis 时的 DB 编号. 默认是0.password: 用于连接有密码的 Redis 服务器.{"conn":"127.0.0.1:11211"}【示例】
- import (
- "fmt"
- "github.com/astaxie/beego"
- "github.com/astaxie/beego/cache"
- _ "github.com/astaxie/beego/cache/redis"
- "time"
- )
-
- func (this *TestController) Test() {
- bm, err := cache.NewCache("redis", `{"key":"127.0.0.1","conn":":6379","dbNum":"0","password":""}`)
- if err != nil {
- fmt.Println(err)
- }
- fmt.Printf("bm = %+vn",bm)
-
- err1 := bm.Put("yisonli", 1, 10*time.Second)
- if err1 != nil {
- fmt.Println(err1)
- }
- redisValue := bm.Get("yisonli")
- fmt.Printf("redisValue = %sn",redisValue)
-
- this.Ctx.Output.Body([]byte("OK"))
- }

执行效果:
- bm = &{p:0xc000210240 conninfo::6379 dbNum:0 key:127.0.0.1 password: maxIdle:3}
- redisValue = 1
注:
1. 示例中使用了redis作为缓存,如果不依赖beego的cache模块,redis还有很多很好用的数据类型和功能方法,如:Hash散列、List列表、Set集合、SortedSet有序集合。
2. 本机启动redis服务,和上文启动mysql类似,只需要一条指令启动docker镜像即可:docker run --name local-redis -p 6379:6379 -v $PWD/data:/data -d redis redis-server --appendonly yes
beego 内置了 session 模块,使用 session 相当方便。
方式1、 在 main 入口函数中设置:beego.BConfig.WebConfig.Session.SessionOn = true
方式2、 通过配置文件配置:sessionon = true
session默认采用 memory 的方式进行存储,如果需要更换别的引擎(以redis为例),需要修改&设置如下配置:
- beego.BConfig.WebConfig.Session.SessionProvider = "redis"
- beego.BConfig.WebConfig.Session.SessionProviderConfig = "127.0.0.1:6379"
【示例】
- func (this *MainController) Get() {
- v := this.GetSession("asta")
- if v == nil {
- this.SetSession("asta", int(1))
- this.Data["num"] = 0
- } else {
- this.SetSession("asta", v.(int)+1)
- this.Data["num"] = v.(int)
- }
- this.Data["Website"] = "beego.me"
- this.Data["Email"] = "astaxie@gmail.com"
- fmt.Printf("%+vn", this.Data)
- this.TplName = "index.tpl"
- }
运行后,多次访问首页的debug输出结果:
- 2019/07/17 20:25:20.235 [I] [asm_amd64.s:1333] http server Running on http://:8080
- map[RouterPattern:/ num:0 Website:beego.me Email:astaxie@gmail.com]
- 2019/07/17 20:25:25.141 [D] [server.go:2741] | 127.0.0.1| 200 | 4.63737ms| match| GET / r:/
- map[num:1 Website:beego.me Email:astaxie@gmail.com RouterPattern:/]
- 2019/07/17 20:25:46.021 [D] [server.go:2741] | 127.0.0.1| 200 | 5.116566ms| match| GET / r:/
- map[RouterPattern:/ num:2 Website:beego.me Email:astaxie@gmail.com]
- 2019/07/17 20:26:00.084 [D] [server.go:2741] | 127.0.0.1| 200 | 1.573909ms| match| GET / r:/
- map[RouterPattern:/ num:3 Website:beego.me Email:astaxie@gmail.com]
- 2019/07/17 20:26:12.470 [D] [server.go:2741] | 127.0.0.1| 200 | 2.652028ms| match| GET / r:/
掌握了以上那么多技能,现在,你对项目的开发有多少把握了呢?
其实,基本已经差不多了,剩下的就是动手实践了。
古人学问无遗力,少壮工夫老始成。
纸上得来终觉浅,绝知此事要躬行。
我是 Yison ,如果我有帮助到你,也请你帮助一下我,随手一个赞对你来说无足轻重,但却是使我不断前行的动力!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。