重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
最近在学习Go语言,利用之前的项目作为案例进行重构。项目背景:php提供TCP服务,硬件连接服务器需要处理信息,然后将处理的信息在发送客户端,客户端拿到信息展示给用户。第一种方案客户端对发送信息的接口进行轮询,检查硬件是否有信息返回,这样不好太浪费资源;第二种方案采用websocket将信息主动发送给客户端,客户端做后续的展示和处理工作;所以最终采用websocket。PHP实现websocket采用GatewayWorker,经过商业论证还是很稳定的。
目前成都创新互联公司已为上1000家的企业提供了网站建设、域名、虚拟空间、绵阳服务器托管、企业网站设计、浔阳网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
在用Go语言重构项目的时候,需要用Go重新搭建Websocket,去网上查了一些资料,利用 gorilla/websocket 在嵌套web框架就可以实现websocket,目前采用Go语言的iris Web框架,接下来就说说我是怎么实现的。
第一个:Beego框架
Beego框架是astaxie的GOWeb开发的开源框架。Beego框架最大的特点是由八个大的基础模块组成,八大基础模块的特点是可以根据自己的需要进行引入,模块相互独立,模块之间耦合性低。
相应的Beego的缺点就是全部使用时比较臃肿,通过bee工具来构建项目时,直接生成项目目录和耦合关系,从而会导致在项目开发过程中受制性较大。
第二个:Gin框架
Gin是一个GOlang的微框架,封装比较优雅,API友好,源码注释比较明确,已经发布了1.0版本;具有快速灵活、容错方便等特点,其实对于golang而言,web框架的依赖远比Python、Java更小。
目前在很多使用golang的中小型公司中进行业务开发,使用Gin框架的很多,大家如果想使用golang进行熟练Web开发,可以多关注一下这个框架。
第三个:Iris框架
Iris框架在其官方网站上被描述为GO开发中最快的Web框架,并给出了多框架和多语言之前的性能对比。目前在github上,Iris框架已经收获了14433个star和1493个fork,可见是非常受欢迎的。
在实际开发中,Iris框架与Gin框架的学习曲线几乎相同,所以掌握了Gin就可以轻松掌握Iris框架。
第四个:Echo框架
也是golang的微型Web框架,其具备快速HTTP路由器、支持扩展中间件,同时还支持静态文件服务、Websocket以及支持制定绑定函数,制定相应渲染函数,并允许使用任意的HTML模版引擎。
这里有个评测:
最快的还是fasthttp,iris也是基于fasthttp的,不会比fasthttp快
Revel Web开源框架
个高效的Go语言Web开发框架, 其思路完全来自 Java 的 Play Framework。
特点
热编译,简单可选,同步(每个请求都创建自己的goroutine来处理。
Go语言Web框架:beego
一个用Go开发的应用框架,思路来自于tornado,路由设计来源于sinatra。
支持特性
MVC;
REST;
智能路由;
日志调试;
配置管理;
模板自动渲染;
layout设计;
中间件插入逻辑;
方便的JSON/XML服务;
1.用{{}}包围的是变量,如 {{testName}} ,这表示把给定变量的值插入, {%%}这是块元素 在faygo里叫tag,常见的有 for , if 等
2.如何在模板中定义变量, 平常我们在使用的模板的时候的常会有这样的需要,在模板中要定义一个变量以方便前端逻辑的实现,在faygo模板中定义变量需要用到标签{%set%}
使用方法
{#定义变量 newName #}
{% set newName = "hello faygo" %}
{#获取变量newName的值#}
{{newName}}
定义用 tag set 取值就是上文所提到的{{}}取值
3.在模板中调用方法
这也是一个非常常见和有用的方法,在faygo中调用方法有两种方式 , 一是在渲染模板时在faygo.Map在加入你要调用的方法 , 二是注册一个全局的方法 (在faygo里叫filter过滤器),我们分别来看一下每个方法的实现
1) 在渲染模板时加入方法(render)
//在后端render时加入方法 testFunc
rErr := ctx.Render(200, switchDir+"index.html", faygo.Map{
"TITLE": title,
"testMap": map[string]string{"aaa": "111111"},
"testFunc": func(s string) string {
return s + " this is test func"
},
})
{#前端模板中调用#}
{{ testFunc("hello") }}
结果如下
hello this is test func
这种方法适合只用于此模板一个特殊方法 , 在其它功能中不通用 ,那么如果想定义一个方法全局都可以使用怎么办,这里就需要注册全局方法了(见下文)
2)注册全局方法(过滤器)
如果想定义一个方法全局都可以使用怎么办 ,这里就需要注册一个方法
// pongo2 注册一个全局过滤器,一般在程序启动时init中注册
//这里注册了一个名叫testFilter的过滤器,指向TestFilterFunc方法
pongo2.RegisterFilter("testFilter", TestFilterFunc)
func TestFilterFunc(in, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
a := in.String() + " this is global filter"
return pongo2.AsValue(a), nil
}
在这里我们看到TestFilterFunc方法里接收参数和返回参数的类型是pongo2.Value和pongo2.Error
在注册过滤器里方法的接收参数和返回参数是固定的这两个不能改变
官网的话:
All functions’ parameters types must be of either your own type or of type *pongo2.Value(no matter how many) and functions must return one value of either type *Value or your own one.
那么我们返回数据时怎么返回? 在上面例子在我们看到了 AsValue 这个方法可以将我们数据返回,我们可以返回struct,map,array,string 等
在前端调用
{{ "hello" | testFilter }}
结果:
hello this is global filter
返回结构体:
type LoginUserInfo struct {
Username string `json:"username"`
Telephone string `json:"telephone"`
Email string `json:"email"`
Level int `json:"level"`
}
func TestFilterFunc(in, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
userInfo := LoginUserInfo{
Username: "userA",
Telephone: "123456",
Email: "123456@test.com",
Level: 1,
}
return pongo2.AsValue(userInfo), nil
}
前端使用:
{#定义一个变量接收struct数据 #}
{% set uinfo = "" | testFilter %}
{#取用户名字#}
{{ uinfo.Username }}
注意,如是 uinfo 只是一个struct 不是struct数组([]uinfo)时 在模板中不能使用{% for %} 使用也不会得到任何数据
如果uinfo是struct数组 在模板中for循环时不要使用 key,val in uinfo
如果uinfo是struct数组 uinfo = []userInfo{}
{#错误示例#}
{% for key,val in uinfo %}
{{val.Username}}
{% endfor %}
struct数据不能使用key,否则循环会执行,但取不到任何数据
{# 正确示例 #}
{% for val in uinfo %}
{{val.Username}}
{% endfor %}
说一下返回map时 用for循环的情况,无论是否是map数组都可以用for key,val in uinfo 来遍历数据
4. 在模板中字符串的连接和宏标签的使用
在模板中有时我们会碰到这样的需要:在模板中有几个变量 ,我们想把这几个变量连接在一起赋值给另一个变量以做其它操作
例: 在模板中有三个变量 host是域名,route是路由地址,param是参数 ,要把这三个变量连接起来赋值给另一个新的变量做urlencode操作。这应该怎么办
因为在模板中使用 + 号连接变量时,程序会认为是数学运算,两个字符串的连接值为0, 如果用内置的filter: join来连接需要传入一个slice,但这三个只是字符串变量。
这个时候我们可能就要用到宏标签了% macro %% endmacro %.
思路是这样的,在宏标签中定义一个宏(可以理解为一个方法),这个宏接收三个参数(参数个数看需求而定),在宏内返回连接的字符串
代码:
{#定义三个变量#}
{% set host="" %}
{% set route="/aaa/bbb" %}
{% set param= "?id=123" %}
{#定义一个宏标签接收三个参数,并返回。注意在宏标签内如果换行,输出的结果中也会有换行,在urlencode的时候也会把换行符进行转义#}
{% macro joinUrl(paramA,paramB,paramC) %}{{paramA}}{{paramB}}{{paramC}}{% endmacro %}
hr
{#定义一个新变量调用宏方法,并将三个参数传入#}
{% set newurl = joinUrl(host,route,param) %}
{#输出newurl的值#}
{{newurl}}br
{#输入出urlencode后的字符串#}
{{newurl|urlencode}}br
结果:
http%3A%2F%2F
在宏标签在也可加入自定义的一些字符串如在上面的宏标签返回结果中要加一个固定字符可以这样写:
{% macro joinUrl(paramA,paramB,paramC) %}{{paramA}}{{paramB}}{{paramC}}from=macro{% endmacro %}