先看看我们要实现的效果截图:
[root@contoso ~]# tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构
/root/code/go/src/contoso.org└── booking
├── debug
├── index.go
├── index.html
├── public
│ ├── footer.html
│ └── header.html
└── static
├── css
├── images
└── js
6 directories,5 files
[root@contoso ~]#
index.html 模板它是主模板,其它模板都是它的子模板,都将被嵌入到index.html模板中
<!DOCTYPE html><!-- 声明当前页面文件格式符合w3c标准,兼容所有浏览器 -->
<html> {{/* index.html 它是页面模板 */}}
{{template "header" .}} {{/* header.html 它是页面嵌入模板,最后的那个点表示将当前模板中的变量传递到header.html模板中 */}}
<body>
<div id="container">
<header>
<div class="t-header">
<div class="t-logo">
<a href="#">
<img src="static/images/logo.png" alt="天猫Tmall.com" width="190px" height="27px"/>
</a>
</div>
</div>
</header>
<section class="main">
</section >
{{template "footer"}} {{/* footer.html 它是页面嵌入模板,双花括号内容后面没有那个点表示footer.html模板中没有变量 */}}
</body>
</html>
子模板header.html 它是页面的嵌入模板
{{define "header"}} {{/* header.html 它是页面的嵌入模板 */}}
<head>
<!-- 声明当前页面编码集:中文(GBK/GB2312),国际编码(utf-8) -->
<Meta http-equiv="Content-Type" content="text/html" charset="utf-8">
<!-- 声明当前页面的三要素:title标签以及keywords和description的Meta标签,三要素一般都要从数据库表里读取 -->
<title>{{.Title}}</title> {{/* index.html模板中的变量传递到header.html模板中使用 */}}
<Meta name="keywords" content="关键词1,关键词2"><!-- 关键词:title和body内容对应的核心关键词,一般不超过100个字符(50个汉字) -->
<Meta name="description" content=""><!-- 内容摘要,一般不超过200个字符(100个汉字) -->
<link type="text/css" rel="stylesheet" href="/static/css/index.css" />
</head>
{{end}} {{/* {{ 嵌入模板定义格式:define "嵌入模板名称"}} {{end}} */}}
子模板footer.html 它是页面的嵌入模板
{{define "footer"}} {{/* footer.html 它是页面的嵌入模板 */}}
<footer>
</footer>
</div>
{{end}} {{/* {{ 嵌入模板定义格式:define "嵌入模板名称"}} {{end}} */}}
index.css静态文件的加载方式必须启动静态文件服务,注意项目静态文件目录结构的定义层次,这个与静态文件服务启动有关系
请留意index.go启动说明,图片,还有js脚本,对于本项目可以直接拷贝图片和js文件到项目对应的目录下,
js该怎么引用,还是象过去那样写到<head></head>标签里
body,div{margin:0;padding:0;}
body{font-size:12px;font-family:"微软雅黑";color:#666;}
html,body{
height: 100%;
}
#container{
/*保证footer是相对于container位置绝对定位*/
position:relative;
width:100%;
min-height:100%;
/*设置padding-bottom值大于等于footer的height值,以保证main的内容能够全部显示出来而不被footer遮盖;*/
padding-bottom: 100px;
Box-sizing: border-Box;
}
header{
width:100%;height:85px;background:#ffffff;
}
header .t-header{width:1000px;height:85px;background:#ffffff;margin:0 auto;}
header .t-header .t-logo{float:left;margin-top:28px;}
header .t-header .t-desc{float:right;line-height:85px;font-size:22px;font-weight:300;}
.main{
width: 100%;
height: 200px;
background: orange;
}
footer{
width: 100%;
height:100px; /* footer的高度一定要是固定值*/
position:absolute;
bottom:0px;
left:0px;
background: #333;
}
index.go HTTP Web Server
package main
import (
"html/template"
"log"
"net/http"
)
func main() {
h := http.FileServer(http.Dir("static"))
http.Handle("/static/",http.StripPrefix("/static/",h)) // 启动静态文件服务
//Header().Set("Expires",time.Now().Format("MON,02 Jan 2006 15:04:05 GMT"))
http.HandleFunc("/",load)
http.ListenAndServe(":8080",nil)
}
func load(w http.ResponseWriter,r *http.Request) {
if r.Method == "GET" {
t,err := template.ParseFiles("index.html","public/header.html","public/footer.html")
if err != nil {
log.Fatal(err)
}
data := struct {
Title string
}{
Title: "品牌街-上天猫,就够了",
}
err = t.Execute(w,data)
if err != nil {
log.Fatal(err)
}
} else {
}
}
顺便说一下静态文件本地缓存,上面默认已经可以缓存静态文件了,状态码 200 OK 、304 Not Modified、200 OK (from cache)的区别
https://www.bokeyy.com/post/200-ok-from-cache-vs-304-not-modified.html 这篇文章讲得很清楚了
举例来说, 客户端第1次请求服务器:你几岁了? 服务器第1次应答客户端:我18岁了。 状态:200 OK =========== 客户端第2次请求服务器:你几岁了?我猜你18岁了。 客户端点击的刷新按钮 服务器第2次应答客户端:靠,你知道还问我? 状态:304 Not Modified =========== 客户端第3次请求服务器:你几岁了?我猜你18岁了。 客户端在地址栏按回车发送请求 服务器第3次应答客户端:靠,你知道还问我? 状态:200 OK (from cache) =========== ... ... ... ... ... ... 第300次请求发送前,直接修改静态文件css或者图片,还是修改css文件的内容实验简单点吧 客户端第300次请求服务器:你几岁了?我猜你18岁了。 客户端在地址栏按回车发送请求 服务器第300次应答客户端:靠,你知道还问我? 状态:200 OK (from cache) =========== 第N次请求发送前,直接修改静态文件css或者图片,还是修改css文件的内容实验简单点吧 客户端第N次请求服务器:你几岁了?我猜你18岁了。 客户端点击的刷新按钮 服务器第N次应答客户端:我19岁了。 状态:200 OK,而不是200 OK (from cache) 结论:因为本地有缓存数据时,不需要向服务器发起http请求,服务器的并发数会明显的减少,可以少处理很多http请求