Go语言Web框架gwk介绍 (二)

HttpResult

凡是实现了HttpResult接口的对象,都可以作为gwk返回Web客户端的内容。HttpResult接口定义非常简单,只有一个方法:

  1. type HttpResult interface {
  2. Execute(ctx *HttpContext) error
  3. }

func Execute(ctx *HttpContext) error 方法定义了应该怎么样将数据返回客户端,*HttpContext 是当前http请求的上下文对象,后文会详细介绍。

gwk内置了支持几种常用的HttpResult。

ContentResult

  1. type ContentResult struct {
  2. ContentType string
  3. Data interface{}
  4. }
  5. func Content(data interface{}, contentType string) *ContentResult {
  6. return &ContentResult{
  7. Data: data,
  8. ContentType: contentType,
  9. }
  10. }

ContentResult对应了raw html数据,直接将Data原样写入到http response中,如果你定义了ContentType参数,会在写Data之前先写http header:Content-Type。

如果Data实现了WriterTo、Reader接口,或者Data是[]byte 或者string,直接将Data写入Response,如果不是的话,gwk调用fmt.Fprintln将Data写入Response。

JsonResult

  1. func Json(a interface{}) *JsonResult

JsonResult顾名思义,先将数据序列化为json格式,再写入Response,默认会将http header的Content-Type设置为"application/json",你也可以先给Content-Type设置一个值来阻止gwk设置Content-Type。

XmlResult

  1. func Xml(a interface{}) *XmlResult

XmlResult将数据序列化为xml格式再写入Response,默认会将Content-Type设置为"text/xml"。

FileResult

  1. func File(path string) *FileResult

FileResult对应静态文件,实际上就是调用http.ServeFile来输出静态文件。 FileResult的path支持两种方式:绝对路径和相对路径,例子如下:

  1. func FileAbsolute(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
  2. return wk.File(path.Join(ctx.Server.Config.RootDir, "public/humans.txt")), nil
  3. }
  4. func FileRelative(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
  5. return wk.File("~/public/humans.txt"), nil
  6. }

如果path以~/开头则为相对路径,否则即为绝对路径。

FileStreamResult

  1. func FileStream(contentType, downloadName string, reader io.Reader, modtime time.Time) *FileStreamResult {
  2. return &FileStreamResult{
  3. ContentType: contentType,
  4. DownloadName: downloadName,
  5. Data: reader,
  6. ModifyTime: modtime,
  7. }
  8. }

FileStreamResult对应一个Stream文件,如果设置了DownloadName参数,则将其作为浏览器保存文件的默认文件名,实际就是设置http header:"Content-Disposition"。

FileStreamResult内部是调用ServeContent。一个简单的例子如下:

  1. // url: get /file/time.txt
  2. server.RouteTable.Get("/file/time.txt").To(FileHelloTime)
  3. func FileHelloTime(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
  4. s := "hello, time is " + time.Now().String()
  5. reader := strings.NewReader(s)
  6. return wk.FileStream("", "hellotime.txt", reader, time.Now()), nil
  7. }

BundleResult

  1. func FileJsBundling(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
  2. files := []string{"xxx/js/main.js", "xxx/js/plugins.js"}
  3. return &wk.BundleResult{Files: files}, nil
  4. }

BundleResult是将若干相同类型的文件打包成一个文件返回,藉此提升响应速度。BundleResult原先是一个用来演示如何自定义HttpResult的demo,现在集成到gwk中。现在的版本还只支持绝对路径,后续的版本可能会支持相对路径。

RedirectResult

  1. func Redirect(urlStr string, permanent bool) *RedirectResult

RedirectResult用来做http重定向,根据permanent参数决定返回 http.StatusMovedPermanently还是http.StatusFound。

NotFoundResult

NotFoundResult默认返回http.StatusNotFound,如果你开启了自定义404页面功能,则按如下逻辑返回:

  1. 如果Request的http header "accept"包含"text/html",先找public路径下的404.html,如果存在则返回404.html的内容。

  2. 如果启用View引擎,并且views目录下存在404.html,则解析模板404.html返回。

  3. 如果Request的http header "accept"包含"text/plain",并且public路径下存在的404.txt,则返回404.txt的内容。

  4. 如果上面的情况都不成立,则返回http.StatusNotFound。

开启了自定义404页面功能的方法是设置config的NotFoundPageEnable为true。设置方式见"配置"章节。

ErrorResult

  1. func Error(message string) *ErrorResult {
  2. return &ErrorResult{
  3. Message: message,
  4. }
  5. }

ErrorResult顾名思义返回错误信息,默认返回http.StatusInternalServerError,如果你开启了自定义错误页面功能,则按如下逻辑返回:

  1. 如果Request的http header "accept"包含"text/html",先找public路径下的error.html,如果存在则返回error.html的内容。

  2. 如果启用View引擎,并且views目录下存在error.html,则解析模板error.html返回。

  3. 如果Request的http header "accept"包含"text/plain",并且public路径下存在的error.txt,则返回error.txt的内容。

  4. 如果上面的情况都不成立,则返回http.http.StatusInternalServerError。

开启了自定义错误页面功能的方法是这是config的ErrorPageEnable为true。

ViewResult

  1. func View(file string) *ViewResult {
  2. return &ViewResult{
  3. File: file,
  4. }
  5. }

ViewResult解析html模板并且输出到Response,因为这一块内容比较多,在"View引擎"一节单独介绍。

JsonpResult

返回Jsonp格式的数据,目前还没有实现。

NotModifiedResult

返回http.StatusNotModified

自定义HttpResult

自定义HttpResult十分简单,只要实现Execute(ctx *HttpContext) error方法就可以了,Go的interface机制让使用第三方的HttpResult或者开发一个HttpResult给别人使用变得很简单。

gwk的demo中包含一个自定义HttpResult的例子QrCodeResult,可以将文本转化为二维码显示,这个例子不兼容App Engine,只能在线下运行demo程序看效果。

模板引擎

作为Web Engine框架,模板引擎是必不可少的,gwk的模板引擎基于Go自带的Html Template,在此基础上添加了一些新的功能。

  • 内存中缓存编译的模板
  • 内置了一系列Template Func
  • 支持模板layout
  • 支持partial view

先看几个具体的模板定义的例子,对gwk的模板有个直观的印象。

layout文件:_layout.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>{{.title}}</title>
  6. <script type="text/javascript">
  7. </script>
  8. <style>
  9. </style>
  10. {{template "head" .}}
  11. </head>
  12. <body>
  13. <div id="header">
  14. {{partial "nav.html" .user }}
  15. </div>
  16. {{/* a comment */}}
  17. {{template "body" .}}
  18. <div id="footer">
  19. build by gwk
  20. </div>
  21. <script type="text/javascript">
  22. </script>
  23. {{template "script" .}}
  24. </body>
  25. </html>

模板文件:basic.html

  1. {{set . "title" "title demo" }}
  2. {{import "_layout.html" }}
  3. {{define "head" }}
  4. <script type="text/javascript">
  5. </script>
  6. <style>
  7. div{padding: 10px;}
  8. </style>
  9. {{end}}
  10. {{define "body" }}
  11. <h1>hello gwk!</h1>
  12. {{raw "<!-- <script><style><html> -->"}}
  13. <div>
  14. <lable for="selected">selected</lable>
  15. <select id="selected">
  16. <option value="" ></option>
  17. <option value="selected" {{selected true}}>selected</option>
  18. </select>
  19. <lable for="notselected">not selected</lable>
  20. <select id="notselected">
  21. <option value="" ></option>
  22. <option value="notselected" {{selected false}}>not selected</option>
  23. </select>
  24. </div>
  25. <div>
  26. <input id="checked" type="checkbox" {{checked true}}>checked</input>
  27. <input id="notchecked" type="checkbox" {{checked false}}>not checked</input>
  28. </div>
  29. <ul>
  30. <li id="eq">eq 123 123 = {{eq 123 123}}</li>
  31. <li id="eq">eqs "123" 123 = {{eqs "123" 123}}</li>
  32. <li id="gt">gt 3.14 3 = {{gt 3.14 3}}</li>
  33. <li id="le">le 1.1 2 = {{le 1.1 2}}</li>
  34. </ul>
  35. <div>{{nl2br "a\nb\nc" }}</div>
  36. <div id="settest-before">settest-before = {{.settest}}</div>
  37. {{set . "settest" "true"}}
  38. <div id="settest-after">settest-after = {{.settest}}</div>
  39. {{partial "user.html" .user}}
  40. {{end}}
  41. {{define "script" }}
  42. <script>
  43. {{jsvar "user" .user}}
  44. </script>
  45. {{end}}

partial view文件:nav.html

  1. <div id="nav">Hi {{.Name}}</div>

另外一个partial view文件:user.html

  1. <ul id="div-{{.Name}}">
  2. <li>name:{{.Name}} </li>
  3. <li>age:{{.Age}}</li>
  4. <li><a href="{{.Web}}">web</a></li>
  5. <li><a href="mailto:{{.Email}}">email</a></li>
  6. </ul>

最后的输出应该类似下面的html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>title demo</title>
  6. <script type="text/javascript">
  7. </script>
  8. <style>
  9. </style>
  10. <script type="text/javascript">
  11. </script>
  12. <style>
  13. div{padding: 10px;}
  14. </style>
  15. </head>
  16. <body>
  17. <div id="header">
  18. <div id="nav">Hi Gopher</div>
  19. </div>
  20. <h1>hello gwk!</h1>
  21. <!-- <script><style><html> -->
  22. <div>
  23. <lable for="selected">selected</lable>
  24. <select id="selected">
  25. <option value="" ></option>
  26. <option value="selected" selected>selected</option>
  27. </select>
  28. <lable for="notselected">not selected</lable>
  29. <select id="notselected">
  30. <option value="" ></option>
  31. <option value="notselected" >not selected</option>
  32. </select>
  33. </div>
  34. <div>
  35. <input id="checked" type="checkbox" checked>checked</input>
  36. <input id="notchecked" type="checkbox" >not checked</input>
  37. </div>
  38. <ul>
  39. <li id="eq">eq 123 123 = true</li>
  40. <li id="eq">eqs "123" 123 = true</li>
  41. <li id="gt">gt 3.14 3 = true</li>
  42. <li id="le">le 1.1 2 = true</li>
  43. </ul>
  44. <div>a<br/>b<br/>c</div>
  45. <div id="settest-before">settest-before = </div>
  46. <div id="settest-after">settest-after = true</div>
  47. <ul id="div-Gopher">
  48. <li>name:Gopher </li>
  49. <li>age:3</li>
  50. <li><a href="http://golang.org">web</a></li>
  51. <li><a href="mailto:gopher@golang.org">email</a></li>
  52. </ul>
  53. <div id="footer">
  54. build by gwk
  55. </div>
  56. <script type="text/javascript">
  57. </script>
  58. <script>
  59. var user = {"Name":"Gopher","Age":3,"Web":"http://golang.org","Email":"gopher@golang.org"};
  60. </script>
  61. </body>
  62. </html>

更多模板的例子可以参考https://github.com/sdming/wk/tree/master/demo/basic/views/user

Template Func

gwk默认添加了若干Template Func

  • eq: 判断是否相等
  • eqs: 转化成字符串,再判断是否相等
  • gt: 大于
  • le: 小于
  • set: 设置map[string]interface{}元素的值
  • raw: 输出非转义的字符串
  • selected: 输出字符串"selected"或者""
  • checked: 输出字符串"checked"或者""
  • nl2br: 将字符串中的"\n"替换为"<br/>"
  • jsvar: 将Go的变量转化为javascript中的变量定义
  • import: 导入模板文件
  • fv: 调用*http.Request.FormValue
  • incl: 判断一个[]string中是否包含字符串v
  • partial: 调用一个partial view

模板layout

你gwk中你可以定义若干个模板layout,然后在每个具体的模板文件中调用函数"import"引用某个layout文件,layout文件的路径为相对于模板根目录的相对路径。

  1. {{import "_layout.html" }}

需要注意的是,import要在模板输出具体内容之前调用才有效。

调用另一个模板

在gwk的模板文件中,可以通过函数partial调用另一个模板文件,这对于web服务端模块化开发来说很有用。在上面例子中定义了一个模板文件user.html来显示user对象的信息,在其他模板文件中就可以直接使用user.html了。

  1. {{partial "user.html" .user}}

模板缓存

默认配置下,gwk在第一次访问某个模板文件时会缓存编译后的模板*template.Template,后续访问这个模板时直接从缓存中读取*template.Template对象,如果模板的物理文件被修改,gwk会从缓存中删除对应的*template.Template对象。gwk使用fsnotify来监控物理文件,详细信息可以访问fsnotify的项目主页。

需要注意的是fsnofity在App Engine上不起作用,其实App Engine的更新机制也决定了不需要物理文件变更监控这样的功能。

你可以在plugin.conf关闭模板缓存功能,配置代码类似:

  1. #GoHtml config
  2. gohtml: {
  3. cache_enable: true
  4. }
  5. # -->end GoHtml

接下里介绍gwk的内部实现机制。

 
 
分类: Go
标签: golangWeb FrameworkGWKMVC

Go语言Web框架gwk介绍2的更多相关文章

  1. Go语言Web框架gwk介绍4

    Go语言Web框架gwk介绍 (四)   事件 gwk支持事件系统,但并没有硬编码有哪些事件,而是采用了比较松散的定义方式. 订阅事件有两种方式: 调用On函数或者OnFunc函数 func On(m ...

  2. Go语言Web框架gwk介绍 3

    Go语言Web框架gwk介绍 (三)   上一篇忘了ChanResult ChanResult 可以用来模拟BigPipe,定义如下 type ChanResult struct { Wait syn ...

  3. Go语言Web框架gwk介绍 1

    Go语言Web框架gwk介绍 (一)   今天看到Golang排名到前30名了,看来关注的人越来越多了,接下来几天详细介绍Golang一个web开发框架GWK. 现在博客园支持markdown格式发布 ...

  4. Go语言Web框架gwk介绍 (一)

    今天看到Golang排名到前30名了,看来关注的人越来越多了,接下来几天详细介绍Golang一个web开发框架GWK. 现在博客园支持markdown格式发布文章么?后台的编辑器不太好用嘛. GWK ...

  5. Go语言Web框架gwk介绍 (五)

    Session Go的net/http本身不带session的机制,需要开发人员自行实现,gwk实现了内存中的session存储机制,如果需要将session存在其他地方比如redis或者memcac ...

  6. Go语言Web框架gwk介绍 (四)

    事件 gwk支持事件系统,但并没有硬编码有哪些事件,而是采用了比较松散的定义方式. 订阅事件有两种方式: 调用On函数或者OnFunc函数 func On(moudle, name string, h ...

  7. Go语言Web框架gwk介绍 (二)

    HttpResult 凡是实现了HttpResult接口的对象,都可以作为gwk返回Web客户端的内容.HttpResult接口定义非常简单,只有一个方法: type HttpResult inter ...

  8. Go语言Web框架gwk介绍 (三)

    上一篇忘了ChanResult ChanResult 可以用来模拟BigPipe,定义如下 type ChanResult struct { Wait sync.WaitGroup Chan chan ...

  9. 最好的6个Go语言Web框架

    原文:Top 6 web frameworks for Go as of 2017 作者:Edward Marinescu 译者:roy 译者注:本文介绍截至目前(2017年)最好的6个Go语言Web ...

随机推荐

  1. Linux-常用命令1---对文件进行查看、复制、移动和分割

    基于Linux的操作系统是一种自由和开放源代码的类UNIX操作系统. Linux的几大特点决定了它的不可代替和无法超越性: (1)免费的/开源的:(2)支持多线程/多用户: (3)安全性好; (4)对 ...

  2. CSS3+HTML5特效2 - 翻转效果

    先看效果,鼠标移上去看看. back front 1. 本实例需要以下元素 a. 容器BOX b. 默认显示元素FRONT c. 翻转显示元素BACK 2. 容器BOX的Height为200px,Wi ...

  3. zsh的安装与配置

    参考: http://cnbin.github.io/blog/2015/06/01/mac-zsh-an-zhuang-he-shi-yong/ http://www.cnblogs.com/ios ...

  4. 条形码(JBarcode)

    一世尘梦 少小离家老大回,妖娆尘世,程序唧唧:问君能有几多愁,恰是满屏BUG无处修. 商品条形码(JBarcode) 之前没有使用过这个,现在使用JBarcode生成商品条形码,工作之前的准备工作: ...

  5. 利用@media screen实现网页布局的自适应,@media screen and

    开始研究响应式web设计,CSS3 Media Queries是入门.Media Queries,其作用就是允许添加表达式用以确定媒体的环境情况,以此来应用不同的样式表.换句话说,其允许我们在不改变内 ...

  6. 表单验证的3个函数ISSET()、empty()、is_numeric()的使用方法

    原文:表单验证的3个函数ISSET().empty().is_numeric()的使用方法 本文就简单讲一下php中表单验证的三个函数,应该比较常用吧,最后给一些示例,请看下文. ISSET();—— ...

  7. Floodlight controller 线程池模型

         官方文档对于ThreadPool的描写叙述是:ThreadPool is a Floodlight module wrapper for a Java's ScheduledExecutor ...

  8. C# 笔试题,看你会几道题

    1.       Which interface you need to implement to support for each? IEnumerator IEnumerable ICompare ...

  9. 快速构建Windows 8风格应用28-临时应用数据

    原文:快速构建Windows 8风格应用28-临时应用数据 本篇博文主要介绍临时应用数据概览.如何构建临时应用数据. 一.临时应用数据概览 临时应用数据相当于网页中缓存,这些数据文件是不能够漫游的,并 ...

  10. Redis源代码分析(二十四)--- tool工具类(2)

    在上篇文章中初步的分析了一下,Redis工具类文件里的一些使用方法,包含2个随机算法和循环冗余校验算法,今天,继续学习Redis中的其它的一些辅助工具类的使用方法.包含里面的大小端转换算法,sha算法 ...