17returncon, nil

18},

19}

ctrls/test_controller.go

1//Redis测试

2funcRedisSetAction(ctx *gin.Context){

3rds := utils.RedisPool.Get();

4count, _ := redis.Int(rds.Do( "GET", "count"))

5count++

6rds.Do( "SET", "count", count)

7ctx.JSON( 200, gin.H{

8"message": count,

9})

10}

2、基于redis连接池存储的session操作;注意这里的连接池是独立于cache操作redis的连接池,需单独配置参数。1//不用连接池

2//store,err:=redis.NewStore( 10, "tcp", "rs1.baidu.com:6379", "",[] byte( "asfajfa;lskjr2"))

3//使用连接池

4store, err := redis.NewStoreWithPool(utils.RedisPool, [] byte( "as&8(0fajfa;lskjr2"))

session配置

1store, err := redis.NewStoreWithPool(utils.RedisPool, [] byte( "as&8(0fajfa;lskjr2"))

2store.Options(sessions.Options{

3"/",

4domain,

5maxage,

6false, //https 时使用

7true, //true:JS脚本无法获取cookie信息

8})

9iferr != nil{

10// Handle the error. Probably bail out if we can't connect.

11fmt.Println( "redis.NewStore error")

12}

13Router.Use(sessions.Sessions(session_name, store))

Sesssion测试

1//Sesssion测试

2funcSessionAction(ctx *gin.Context){

3session := sessions.Default(ctx)

4varcount int

5v := session.Get( "count")

6ifv == nil{

7count = 0

8} else{

9count = v.( int)

10count += 1

11}

12session.Set( "count", count)

13session.Save()

14ctx.JSON( 200, gin.H{ "count": count})

15}

3、基于xorm的数据库操作,主从分离配置,支持多从库配置,鲜活连接定时PING操作,集成xorm/cmd;

部分代码展示,完整代码见:models/orm.go

1//从库添加

2slaves := utils.Config.Section( "mysql_slave").Keys()

3for_, s_dsn := rangeslaves {

4_dbs, err := xorm.NewEngine( "mysql", s_dsn.String())

5_dbs.SetMaxIdleConns( 10)

6_dbs.SetMaxOpenConns( 200)

7_dbs.ShowSQL( true)

8_dbs.ShowExecTime( true)

9

10iferr!= nil{

11fmt.Println(err)

12} else{

13dbs = append(dbs, _dbs)

14}

15}

4、基于rabbitmq的队列应用,注意生产者与消费者队列名称的一致性多个任务可发送到一个队列,也可以灵活应用一个队列一个任务; 生产者与消费者消息传递的是序列化的结构体,结构体由生产者提供,并自行反序列化操作;

- 消费者: console/queue_daemon.go (队列需要单独控制台命令启动,与http服务独立[避免相互影响];)

1subscriber := new(jobs.Subscribe)

2forever := make( chanbool)

3q := queue.NewQueue()

4//队列执行的任务需要注册方可执行

5q.PushJob( "Dosome",jobs.HandlerFunc(subscriber.Dosome))

6//q.PushJob("Fusome",jobs.HandlerFunc(subscriber.Fusome))

7//提前规划好队列,可按延时时间来划分。可多个任务由一个队列来执行,也可以一个任务一个队列,一个队列可启动多个消费者

8goq.NewShareQueue( "SomeQueue")

9//go q.NewShareQueue("SomeQueue")

10//go q.NewShareQueue("SomeQueue")

11deferq.Close()

12<-forever

- 控制台生产者(这里仅测试使用,正式应用一般在web代码中)

console/send_single.go

1forever := make( chanbool)

2gofunc(){

3fori := 0; i < 1000000; i++ {

4queue.NewSender( "SomeQueue", "Dosome", jobs.Subscribe{Name: "We are doing..."+ strconv.Itoa(i)}).Send()

5}

6}()

7deferqueue.SendConn.Close()

8<-forever

- WEB测试生产者:http://localhost:8080/queue

1//队列生产者测试

2funcQueueAction(ctx *gin.Context){

3queue.NewSender( "SomeQueue", "Dosome", jobs.Subscribe{Name: "We are doing..."}).Send()

4}

5、csrf防跨站攻击

此功能集成此中间件完成点这里,更多中间件。 这里要重点说一下,utrack/gin-csrf这个中间件没有加白名单机制排除一些例外,这在实际应用中是很常见的,尤其是对外合作接口中。 我把此中间件代码集成到我自己的代码中来,把白名单功能补上了。这里直接用包名+函数名来定位,在配置文件conf/csrf_except.ini中配置, key值随意,不空,不重复即可,因不是实时读取,修改后需要重启web服务才生效。

- 应用代码route/router.go

1Router.Use( csrf.Middleware( csrf.Options{

2Secret: csrfscret,

3ErrorFunc: func(c *gin.Context) {

4c. String(400, "CSRF token mismatch")

5c. Abort()

6},

7}))

- 补丁代码:middleware/csrf/csrf.go

1fn := c.HandlerName();

2fn = fn[strings.LastIndex(fn, "/"):]

3

4for_, action := rangeIgnoreAction {

5if(strings.Contains(fn, action)) {

6fmt.Println(action)

7c.Next()

8return

9}

10}

6、数据验证,可自定义友好错误提示,更多实例参考;

ctrls/users/user_controller.go 中 UserAddAction()

1//参数检验

2rules := govalidator.MapData{

3"name": [] string{ "required", "between:3,8"},

4"age": [] string{ "digits:11"},

5}

6

7messages := govalidator.MapData{

8"name": [] string{ "required:用户名不能为空", "between:3到8位"},

9"age": [] string{ "digits:手机号码为11位数字"},

10}

11

12opts := govalidator.Options{

13Request: ctx.Request, // request object

14Rules: rules, // rules map

15Messages: messages, // custom message map (Optional)

16RequiredDefault: false, // all the field to be pass the rules

17}

18v := govalidator.New(opts)

19e := v.Validate()

20

21//校验结果判断

22iflen(e)> 0{

23ctx.JSON( 200, e)

24return

25}

7、INI配置文件读取操作,可分别加载多个配置文件;

utils/config.go

1RootPath= "/Users/baidu/data/golang/gopath/src/go-gin-mvc"

2var errerror

3Config, err= ini.Load(RootPath+ "/conf/config.ini");

4iferr!= nil {

5fmt.Printf( "Fail to read file: %v", err)

6os. Exit( 1)

7}

应用实例

models/orm.go

1//从库添加

2slaves := utils.Config.Section( "mysql_slave").Keys()

3for_, s_dsn := rangeslaves {

4_dbs, err := xorm.NewEngine( "mysql", s_dsn.String())

5...

6}

8、定时任务;

main.go

1//定时程序启动

2c := cron. New()

3//数据库状态检查

4c.AddFunc( "*/600 * * * * *", models.DbCheck)

5c.Start()

cmd/xorm安装注意事项正常安装命令:1goget github.com/ go-xorm/cmd/xorm

但会报错,有两个包无法安装,

1cloud.google.com/ go/civil

2golang.org/x/crypto/md4

移步到https://github.com/GoogleCloudPlatform/google-cloud-go下载相应的包

GOPATH目录下新建cloud.google.com 文件夹(与github.com同级)

1cloud.google.com/ go/civil

2golang.org/x/crypto/md4

进入cmd/xorm 运行命令

1gobuild

查看帮助 xorm help reverse

xorm生成struct1xormreverse mysql "root:12345678@tcp(dbm1.baidu.com:3306)/test?charset=utf8".

项目地址:https://github.com/mydevc/go-gin-mvc

ID:Golangweb