Go语言网络搭建

Go语言强大的包使得网络编程变得轻松。

碎碎念

首先,需要导入http包。

import (
    "net/http"
)

在主函数上还要写上这么一句话

http.ListenAndServe(":80", nil)

来监听端口。端口不一定是80就是了……

使用http.HandleFunc(string, func)方法可以给每一个用户请求访问的网址路径指定不同的处理函数,以达到用户访问不同资源返回不同结果的效果。

用户访问的网站资源路径跟服务器的文件组织路径没有任何关系。用户访问www.example.com/的时候,www.example.com的服务器获悉用户希望访问位于/的资源,因此通过HandleFunc绑定的函数将结果(网页内容)返回给网站的访问者。网页基本上不可能也位于服务器的/位置——首先,/是个目录,不是网页文件;其次,在服务器的根目录放置网页内容是典型的迷惑行为。实际上,服务器可能实际上是将存放于其他地方的网页文件发送给访问者,又或者是动态生成网页的内容,又或者是直接翻数据库找到内容发送回去——事实上服务器上都不一定有一个传统意义上,完整的.html文件。一切的一切最后仅仅是发送出能够让让用户代理(浏览器)正确解析并且显示的一大段字符串而已。结果才是重要的,过程谁也不知道。

当网站规模变大的时候,对用户的每一个资源请求都写一个对应的函数来处理请求,无论是在工程上还是在理论上都是很不现实的“愚蠢”行为。难看,难读,难维护,而且还是高重复度工作。何况当用户访问不存在的资源的时候如何返回错误信息也是很大的问题——用户有无数种访问错误资源的方法。如何简化这类事务以及提供更好的鲁棒性是一直在探究的问题。

用户访问的资源分为“静态资源”和“动态资源”两类。

使用http包处理静态资源请求

静态资源不会经常变动,尤其是不会随着访问用户的变化而变化。静态资源通常出没于整个网站的各个角落,最典型的莫过于各类css文件还有js文件以及各类多媒体文件了。

一个自然的想法是,将这些静态资源整合在一起,放置在服务器的某个角落。用户代理想要访问这些资源的时候,处理函数顺着用户访问资源的路径,顺着文件系统找过去,并且将找到的文件发送给用户代理。

这个想法背离了之前提到的「URL与服务器的实际文件分布完全无关」的特点,因为用户访问的资源的路径跟处理程序在服务器上访问资源的路径是一致的。但是这样可以大大减少程序员的负担,因此还是被广泛应用了。

http包提供了一个固定套路来处理这类需求,请看如下代码。

fs := http.FileServer(http.Dir("服务器上/静态资源的/根目录"))
http.Handle("URL中/静态资源的/根目录", http.StripPrefix("URL中/静态资源的/根目录", fs))

举个例子。common.jsuniversal.css文件分别位于服务器的/home/server/assets/js/目录和/home/server/assets/css/目录当中,而用户分别通过/js/common.js/css/universal.css来定位它。那么,上述代码就将用户的访问请求自动重定向到服务器的/home/server/assets/文件夹开始寻找。找得到就发送,找不到就是404。

使用text包处理模版

常见的动态资源请求,比如说,发生在不同用户需要看到同一个界面的不同版本上。用户登陆个人主页,右上角显示了他的用户名。在不考虑xhr的情况下,最常见的实现方法就是html模版——所有人的个人主页都长一个样,那么事先写好一个只留下用户名一栏没有写定数据的模版,用户请求的时候首先将用户的身份填进模版,然后将填好的模版发送出去,完美。

负责模版的模块是text/template。示范代码如下所示。

import (
    "net/http"
    "text/template"
)

type HomepageData struct {
    PageTitle string
    Uname string
}

func templateHandler(w http.ResponseWriter, r *http.Request) {
    tmpl := template.Must(template.ParseFiles("/模版/路径.html"))
    data := HomepageData {
        PageTitle: "Welcome" + username,
        Uname: username
    }
    tmpl.Execute(w, data)
}

func main() {
    ...

    http.HandleFunc("URL/资源/路径", templateHandler)
    
    ...
}
<h1>{{.PageTitle}}</h1>
<h2>{{.Uname}}</h2>

除了templateHandler之外,其他内容可以不看。首先,第一行定义了一个从文件创建的模版对象。随后下面一行定义了一个用来填充这个模版的结构体对象,最后利用这个结构体对象使用模版的Execute方法进行填充。这样就可以针对不同的username给出不一样的网页内容了。

第三方解决方案

第三方开发者也给出了自己的解决方案。有些是对Go语言标准库的包装,还有些就是重新造轮子了。由于第三方库数量繁多,在此不展开叙述了。

以上。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值