HttpResult
凡是实现了HttpResult接口的对象,都可以作为gwk返回Web客户端的内容。HttpResult接口定义非常简单,只有一个方法:
type HttpResult interface {
Execute(ctx *HttpContext) error
}
func Execute(ctx *HttpContext) error 方法定义了应该怎么样将数据返回客户端,*HttpContext 是当前http请求的上下文对象,后文会详细介绍。
gwk内置了支持几种常用的HttpResult。
ContentResult
type ContentResult struct {
ContentType string
Data interface{}
}
func Content(data interface{}, contentType string) *ContentResult {
return &ContentResult{
Data: data,
ContentType: contentType,
}
}
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
func Json(a interface{}) *JsonResult
JsonResult顾名思义,先将数据序列化为json格式,再写入Response,默认会将http header的Content-Type设置为"application/json",你也可以先给Content-Type设置一个值来阻止gwk设置Content-Type。
XmlResult
func Xml(a interface{}) *XmlResult
XmlResult将数据序列化为xml格式再写入Response,默认会将Content-Type设置为"text/xml"。
FileResult
func File(path string) *FileResult
FileResult对应静态文件,实际上就是调用http.ServeFile来输出静态文件。 FileResult的path支持两种方式:绝对路径和相对路径,例子如下:
func FileAbsolute(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
return wk.File(path.Join(ctx.Server.Config.RootDir, "public/humans.txt")), nil
}
func FileRelative(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
return wk.File("~/public/humans.txt"), nil
}
如果path以~/开头则为相对路径,否则即为绝对路径。
FileStreamResult
func FileStream(contentType, downloadName string, reader io.Reader, modtime time.Time) *FileStreamResult {
return &FileStreamResult{
ContentType: contentType,
DownloadName: downloadName,
Data: reader,
ModifyTime: modtime,
}
}
FileStreamResult对应一个Stream文件,如果设置了DownloadName参数,则将其作为浏览器保存文件的默认文件名,实际就是设置http header:"Content-Disposition"。
FileStreamResult内部是调用ServeContent。一个简单的例子如下:
// url: get /file/time.txt
server.RouteTable.Get("/file/time.txt").To(FileHelloTime)
func FileHelloTime(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
s := "hello, time is " + time.Now().String()
reader := strings.NewReader(s)
return wk.FileStream("", "hellotime.txt", reader, time.Now()), nil
}
BundleResult
func FileJsBundling(ctx *wk.HttpContext) (result wk.HttpResult, err error) {
files := []string{"xxx/js/main.js", "xxx/js/plugins.js"}
return &wk.BundleResult{Files: files}, nil
}
BundleResult是将若干相同类型的文件打包成一个文件返回,藉此提升响应速度。BundleResult原先是一个用来演示如何自定义HttpResult的demo,现在集成到gwk中。现在的版本还只支持绝对路径,后续的版本可能会支持相对路径。
RedirectResult
func Redirect(urlStr string, permanent bool) *RedirectResult
RedirectResult用来做http重定向,根据permanent参数决定返回 http.StatusMovedPermanently还是http.StatusFound。
NotFoundResult
NotFoundResult默认返回http.StatusNotFound,如果你开启了自定义404页面功能,则按如下逻辑返回:
-
如果Request的http header "accept"包含"text/html",先找public路径下的404.html,如果存在则返回404.html的内容。
-
如果启用View引擎,并且views目录下存在404.html,则解析模板404.html返回。
-
如果Request的http header "accept"包含"text/plain",并且public路径下存在的404.txt,则返回404.txt的内容。
-
如果上面的情况都不成立,则返回http.StatusNotFound。
开启了自定义404页面功能的方法是设置config的NotFoundPageEnable为true。设置方式见"配置"章节。
ErrorResult
func Error(message string) *ErrorResult {
return &ErrorResult{
Message: message,
}
}
ErrorResult顾名思义返回错误信息,默认返回http.StatusInternalServerError,如果你开启了自定义错误页面功能,则按如下逻辑返回:
-
如果Request的http header "accept"包含"text/html",先找public路径下的error.html,如果存在则返回error.html的内容。
-
如果启用View引擎,并且views目录下存在error.html,则解析模板error.html返回。
-
如果Request的http header "accept"包含"text/plain",并且public路径下存在的error.txt,则返回error.txt的内容。
-
如果上面的情况都不成立,则返回http.http.StatusInternalServerError。
开启了自定义错误页面功能的方法是这是config的ErrorPageEnable为true。
ViewResult
func View(file string) *ViewResult {
return &ViewResult{
File: file,
}
}
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{.title}}</title>
<script type="text/javascript">
</script>
<style>
</style>
{{template "head" .}}
</head>
<body>
<div id="header">
{{partial "nav.html" .user }}
</div>
{{/* a comment */}}
{{template "body" .}}
<div id="footer">
build by gwk
</div>
<script type="text/javascript">
</script>
{{template "script" .}}
</body>
</html>
模板文件:basic.html
{{set . "title" "title demo" }}
{{import "_layout.html" }}
{{define "head" }}
<script type="text/javascript">
</script>
<style>
div{padding: 10px;}
</style>
{{end}}
{{define "body" }}
<h1>hello gwk!</h1>
{{raw "<!-- <script><style><html> -->"}}
<div>
<lable for="selected">selected</lable>
<select id="selected">
<option value="" ></option>
<option value="selected" {{selected true}}>selected</option>
</select>
<lable for="notselected">not selected</lable>
<select id="notselected">
<option value="" ></option>
<option value="notselected" {{selected false}}>not selected</option>
</select>
</div>
<div>
<input id="checked" type="checkbox" {{checked true}}>checked</input>
<input id="notchecked" type="checkbox" {{checked false}}>not checked</input>
</div>
<ul>
<li id="eq">eq 123 123 = {{eq 123 123}}</li>
<li id="eq">eqs "123" 123 = {{eqs "123" 123}}</li>
<li id="gt">gt 3.14 3 = {{gt 3.14 3}}</li>
<li id="le">le 1.1 2 = {{le 1.1 2}}</li>
</ul>
<div>{{nl2br "a\nb\nc" }}</div>
<div id="settest-before">settest-before = {{.settest}}</div>
{{set . "settest" "true"}}
<div id="settest-after">settest-after = {{.settest}}</div>
{{partial "user.html" .user}}
{{end}}
{{define "script" }}
<script>
{{jsvar "user" .user}}
</script>
{{end}}
partial view文件:nav.html
<div id="nav">Hi {{.Name}}</div>
另外一个partial view文件:user.html
<ul id="div-{{.Name}}">
<li>name:{{.Name}} </li>
<li>age:{{.Age}}</li>
<li><a href="{{.Web}}">web</a></li>
<li><a href="mailto:{{.Email}}">email</a></li>
</ul>
最后的输出应该类似下面的html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title demo</title>
<script type="text/javascript">
</script>
<style>
</style>
<script type="text/javascript">
</script>
<style>
div{padding: 10px;}
</style>
</head>
<body>
<div id="header">
<div id="nav">Hi Gopher</div>
</div>
<h1>hello gwk!</h1>
<!-- <script><style><html> -->
<div>
<lable for="selected">selected</lable>
<select id="selected">
<option value="" ></option>
<option value="selected" selected>selected</option>
</select>
<lable for="notselected">not selected</lable>
<select id="notselected">
<option value="" ></option>
<option value="notselected" >not selected</option>
</select>
</div>
<div>
<input id="checked" type="checkbox" checked>checked</input>
<input id="notchecked" type="checkbox" >not checked</input>
</div>
<ul>
<li id="eq">eq 123 123 = true</li>
<li id="eq">eqs "123" 123 = true</li>
<li id="gt">gt 3.14 3 = true</li>
<li id="le">le 1.1 2 = true</li>
</ul>
<div>a<br/>b<br/>c</div>
<div id="settest-before">settest-before = </div>
<div id="settest-after">settest-after = true</div>
<ul id="div-Gopher">
<li>name:Gopher </li>
<li>age:3</li>
<li><a href="http://golang.org">web</a></li>
<li><a href="mailto:gopher@golang.org">email</a></li>
</ul>
<div id="footer">
build by gwk
</div>
<script type="text/javascript">
</script>
<script>
var user = {"Name":"Gopher","Age":3,"Web":"http://golang.org","Email":"gopher@golang.org"};
</script>
</body>
</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文件的路径为相对于模板根目录的相对路径。
{{import "_layout.html" }}
需要注意的是,import要在模板输出具体内容之前调用才有效。
调用另一个模板
在gwk的模板文件中,可以通过函数partial调用另一个模板文件,这对于web服务端模块化开发来说很有用。在上面例子中定义了一个模板文件user.html来显示user对象的信息,在其他模板文件中就可以直接使用user.html了。
{{partial "user.html" .user}}
模板缓存
默认配置下,gwk在第一次访问某个模板文件时会缓存编译后的模板*template.Template,后续访问这个模板时直接从缓存中读取*template.Template对象,如果模板的物理文件被修改,gwk会从缓存中删除对应的*template.Template对象。gwk使用fsnotify来监控物理文件,详细信息可以访问fsnotify的项目主页。
需要注意的是fsnofity在App Engine上不起作用,其实App Engine的更新机制也决定了不需要物理文件变更监控这样的功能。
你可以在plugin.conf关闭模板缓存功能,配置代码类似:
#GoHtml config
gohtml: {
cache_enable: true
}
# -->end GoHtml
接下里介绍gwk的内部实现机制。
相关推荐
Go语言实现的Web Sever Framework. 启动代码: // ./demo/basic/main.go for more detail server, err := wk.NewDefaultServer() if err != nil { fmt.Println("NewDefaultServer error", err) return } ...
ZC_GWK.exe
Reno4 reno4 pro x50 x50 pro nex PCB文件 gerber文件T9510GWK1.zip p40 p40 pro PCB文件
华为OPPO VIVO 新款原理图位号图 P40 P40 PRO MATE40 MATE40 PRO ,麒麟990 980 970 MTK 高通芯片 华为 小米 OPPO新款原理图位号图 P40 P40 PRO MATE40 MATE40 PRO ,麒麟990 980 970 MTK 高通图纸.Redmi K30 Pro ...
S8600.gwk FINDX 2 PRO RENO4 RENO4 PRO ACER2 畅享20 Pro Nova7 BD包海外刷机包
naver-gw-kit 用于naver Kerberos身份验证和rlogin的网关脚本(从派生) 安装 注意:Gw服务器可能无法访问github服务器。...alias gwk "gwk.sh" $ gwk 变更记录 exec_kinit无法正常工作,因此可以直接执行
雷石点歌机单机版U盘加歌说明文档(官方整理文档特别详细)看完就会
防暴搜寻 开源,分布式,简单高效的全文...Riot使用go模块或dep管理依赖关系。 安装/更新 go get -u github.com/go-ego/riot go get -u github.com/go-ego/re 暴动 创建一个新的防暴应用程序 $ re riot my-riotapp 重
本书介绍Linux环境下的编程方法,内容包括Linux系统命令、 Shell脚本、编程语言(gawk、Perl)、系统内核、安全体系、X Window等,内容丰富、论述全面,涵盖了Linux系统的方方面面。本书附带光盘包括了RedHat Linux...
map gwk : call Focus ( ' up ' , ' k ' ) map gwj : call Focus ( ' down ' , ' j ' ) i3配置需要使用以下绑定进行更新。 bindsym --release $mod+h exec "i3-vim-focus left" bindsym --release $mod+j exec ...
线性表的定义、建立、操作线性表的有关知识、有关内容内容速度测试得分