回到简体

This commit is contained in:
chai2010
2016-02-15 11:06:34 +08:00
parent 9e878f9944
commit 2b37b23285
177 changed files with 2354 additions and 2354 deletions

View File

@@ -1,8 +1,8 @@
## 4.6. 文本和HTML模
## 4.6. 文本和HTML模
前面的例子,是最簡單的格式化使用Printf是完全足的。但是有時候會需要複雜的打印格式,這時候一般需要格式化代碼分離出來以便更安全地改。這寫功能是由text/template和html/template等模包提供的,它提供了一個將變量值填充到一文本或HTML格式的模闆的機製
前面的例子,是最简单的格式化使用Printf是完全足的。但是有时候会需要复杂的打印格式,这时候一般需要格式化代码分离出来以便更安全地改。这写功能是由text/template和html/template等模包提供的,它提供了一个将变量值填充到一文本或HTML格式的模板的机制
個模闆是一字符串或一文件,里面包含了一或多個由雙花括包含的`{{action}}`象。大部分的字符串是按面值打印,但是對於actions部分將觸發其它的行。每actions都包含了一用模闆語言書寫的表式,一action雖然簡短但是可以輸出複雜的打印值,模闆語言包含通過選擇結構體的成員、調用函或方法、表式控流if-else句和range循環語句,有其它例化模闆等諸多特性。下面是一個簡單的模字符串:
个模板是一字符串或一文件,里面包含了一或多个由双花括包含的`{{action}}`象。大部分的字符串是按面值打印,但是对于actions部分将触发其它的行。每actions都包含了一用模板语言书写的表式,一action虽然简短但是可以输出复杂的打印值,模板语言包含通过选择结构体的成员、调用函或方法、表式控流if-else句和range循环语句,有其它例化模板等诸多特性。下面是一个简单的模字符串:
{% raw %}
@@ -21,11 +21,11 @@ Age: {{.CreatedAt | daysAgo}} days
{% raw %}
這個模闆先打印匹配到的issue總數,然打印每issue的編號、創建用戶、標題還有存在的時間。對於每一action都有一個當前值的概念,對應點操作符,作“.”。前值“.”最初被初始化爲調用模是的參數,在前例子中對應github.IssuesSearchResult型的量。模`{{.TotalCount}}`對應action將展開爲結構體中TotalCount成以默的方式打印的值。模`{{range .Items}}``{{end}}`對應一個循環action因此它直接的容可能被展多次,循每次迭代的前值對應當前的Items元素的值。
这个模板先打印匹配到的issue总数,然打印每issue的编号、创建用户、标题还有存在的时间。对于每一action都有一个当前值的概念,对应点操作符,作“.”。前值“.”最初被初始化为调用模是的参数,在前例子中对应github.IssuesSearchResult型的量。模`{{.TotalCount}}`对应action将展开为结构体中TotalCount成以默的方式打印的值。模`{{range .Items}}``{{end}}`对应一个循环action因此它直接的容可能被展多次,循每次迭代的前值对应当前的Items元素的值。
{% endraw %}
在一action中`|`操作符表示前一個表達式的果作爲後一個函數的輸入,類似於UNIX中管道的概念。在Title一行的action中第二操作是一printf函,是一個基於fmt.Sprintf實現的內置函,所有模都可以直接使用。對於Age部分第二個動作是一叫daysAgo的函,通time.Since函數將CreatedAt成員轉換爲過去的時間長度:
在一action中`|`操作符表示前一个表达式的果作为后一个函数的输入,类似于UNIX中管道的概念。在Title一行的action中第二操作是一printf函,是一个基于fmt.Sprintf实现的内置函,所有模都可以直接使用。对于Age部分第二个动作是一叫daysAgo的函,通time.Since函数将CreatedAt成员转换为过去的时间长度:
```Go
func daysAgo(t time.Time) int {
@@ -33,9 +33,9 @@ func daysAgo(t time.Time) int {
}
```
需要意的是CreatedAt的參數類型是time.Time不是字符串。以同的方式,我可以通過定義一些方法來控製字符串的格式化§2.5),一個類型同可以定自己的JSON編碼和解碼行爲。time.Time類型對應的JSON值是一個標準時間格式的字符串。
需要意的是CreatedAt的参数类型是time.Time不是字符串。以同的方式,我可以通过定义一些方法来控制字符串的格式化§2.5),一个类型同可以定自己的JSON编码和解码行为。time.Time类型对应的JSON值是一个标准时间格式的字符串。
生成模闆的輸出需要兩個處理步。第一步是要分析模闆併轉爲內部表示,然後基於指定的輸入執行模。分析模部分一般需要行一次。下面的代碼創建併分析上面定的模templ。意方法調用鏈的順template.New先創建併返迴一個模闆Funcs方法daysAgo等自定義函數註冊到模中,併返迴模闆;最後調用Parse函分析模
生成模板的输出需要两个处理步。第一步是要分析模板并转为内部表示,然后基于指定的输入执行模。分析模部分一般需要行一次。下面的代码创建并分析上面定的模templ。意方法调用链的顺template.New先创建并返回一个模板Funcs方法daysAgo等自定义函数注册到模中,并返回模板;最后调用Parse函分析模
```Go
report, err := template.New("report").
@@ -46,9 +46,9 @@ if err != nil {
}
```
爲模闆通常在編譯時就測試好了,如果模解析失敗將是一致命的錯誤。template.Must助函可以簡化這個致命錯誤的處理:它接受一個模闆和一error型的參數,檢測error是否nil如果不是nil則發出panic常),然後返迴傳入的模。我們將在5.9節再討論這個話題
为模板通常在编译时就测试好了,如果模解析失败将是一致命的错误。template.Must助函可以简化这个致命错误的处理:它接受一个模板和一error型的参数,检测error是否nil如果不是nil则发出panic常),然后返回传入的模。我们将在5.9节再讨论这个话题
一旦模闆已經創建、註冊了daysAgo函數、併通過分析和檢測,我就可以使用github.IssuesSearchResult作爲輸入源、os.Stdout作爲輸出源來執行模
一旦模板已经创建、注册了daysAgo函数、并通过分析和检测,我就可以使用github.IssuesSearchResult作为输入源、os.Stdout作为输出源来执行模
```Go
var report = template.Must(template.New("issuelist").
@@ -66,7 +66,7 @@ func main() {
}
```
程序出一個純文本告:
程序出一个纯文本告:
```
$ go build gopl.io/ch4/issuesreport
@@ -86,9 +86,9 @@ Age: 695 days
...
```
現在讓我們轉到html/template模包。它使用和text/template包相同的API和模闆語言,但是增加了一個將字符串自動轉義特性,可以避免入字符串和HTML、JavaScript、CSS或URL語法産生衝突的問題。這個特性可以避免一些期存在的安全問題,比如通生成HTML入攻,通過構造一含有意代碼的問題標題,這些都可能讓模闆輸出錯誤的輸出,從而讓他們控製頁面。
现在让我们转到html/template模包。它使用和text/template包相同的API和模板语言,但是增加了一个将字符串自动转义特性,可以避免入字符串和HTML、JavaScript、CSS或URL语法产生冲突的问题。这个特性可以避免一些期存在的安全问题,比如通生成HTML入攻,通过构造一含有意代码的问题标题,这些都可能让模板输出错误的输出,从而让他们控制页面。
下面的模以HTML格式出issue列表。意import句的不同:
下面的模以HTML格式出issue列表。意import句的不同:
{% raw %}
@@ -119,26 +119,26 @@ var issueList = template.Must(template.New("issuelist").Parse(`
{% endraw %}
下面的命令在新的模闆上執行一稍微不同的査詢
下面的命令在新的模板上执行一稍微不同的查询
```
$ go build gopl.io/ch4/issueshtml
$ ./issueshtml repo:golang/go commenter:gopherbot json encoder >issues.html
```
4.4示了在web瀏覽器中的效果。每issue包含到Github對應頁面的接。
4.4示了在web浏览器中的效果。每issue包含到Github对应页面的接。
![](../images/ch4-04.png)
4.4中issue有包含會對HTML格式産生衝突的特殊字符,但是我們馬上將看到標題中含有`&``<`字符的issue。下面的命令選擇了兩個這樣的issue
4.4中issue有包含会对HTML格式产生冲突的特殊字符,但是我们马上将看到标题中含有`&``<`字符的issue。下面的命令选择了两个这样的issue
```
$ ./issueshtml repo:golang/go 3133 10535 >issues2.html
```
4.5示了該査詢的結果。html/template包已經自動將特殊字符轉義,因此我依然可以看到正的字面值。如果我使用text/template包的這2個issue將會産生錯誤,其中“&amp;lt;”四字符將會被當作小字符“<理,同&lt;link&gt;”字符串將會被當作一個鏈接元素理,它們都會導致HTML文檔結構的改變,從而導致有未知的風險
4.5示了该查询的结果。html/template包已经自动将特殊字符转义,因此我依然可以看到正的字面值。如果我使用text/template包的这2个issue将会产生错误,其中“&amp;lt;”四字符将会被当作小字符“<理,同&lt;link&gt;”字符串将会被当作一个链接元素理,它们都会导致HTML文档结构的改变,从而导致有未知的风险
也可以通過對信任的HTML字符串使用template.HTML類型來抑製這種自動轉義的行爲。還有很多采用型命名的字符串型分别對應信任的JavaScript、CSS和URL。下面的程序演示了兩個使用不同型的相同字符串生的不同A是一普通字符串B是一信任的template.HTML字符串型。
也可以通过对信任的HTML字符串使用template.HTML类型来抑制这种自动转义的行为。还有很多采用型命名的字符串型分别对应信任的JavaScript、CSS和URL。下面的程序演示了两个使用不同型的相同字符串生的不同A是一普通字符串B是一信任的template.HTML字符串型。
![](../images/ch4-05.png)
@@ -163,15 +163,15 @@ func main() {
{% endraw %}
4.6示了出現在瀏覽器中的模闆輸出。我看到A的黑體標記被轉義失效了但是B有。
4.6示了出现在浏览器中的模板输出。我看到A的黑体标记被转义失效了但是B有。
![](../images/ch4-06.png)
們這里隻講述了模闆繫統中最基本的特性。一如往,如果想了解更多的信息,自己看包文
们这里只讲述了模板系统中最基本的特性。一如往,如果想了解更多的信息,自己看包文
```
$ go doc text/template
$ go doc html/template
```
**練習 4.14** 建一web服器,査詢一次GitHub生成BUG告、里程碑和對應的用信息。
**练习 4.14** 建一web服器,查询一次GitHub生成BUG告、里程碑和对应的用信息。