mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-12-18 19:54:21 +08:00
回到简体
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
## 12.7. 獲取結構體字段標識
|
||||
## 12.7. 获取结构体字段标识
|
||||
|
||||
在4.5節我們使用構體成員標籤用於設置對應JSON對應的名字。其中json成員標籤讓我們可以選擇成員的名字和抑製零值成員的輸出。在本節,我們將看到如果通過反射機製類獲取成員標籤。
|
||||
在4.5节我们使用构体成员标签用于设置对应JSON对应的名字。其中json成员标签让我们可以选择成员的名字和抑制零值成员的输出。在本节,我们将看到如果通过反射机制类获取成员标签。
|
||||
|
||||
對於一個web服務,大部分HTTP處理函數要做的第一件事情就是展開請求中的參數到本地變量中。我們定義了一個工具函數,叫params.Unpack,通過使用結構體成員標籤機製來讓HTTP處理函數解析請求參數更方便。
|
||||
对于一个web服务,大部分HTTP处理函数要做的第一件事情就是展开请求中的参数到本地变量中。我们定义了一个工具函数,叫params.Unpack,通过使用结构体成员标签机制来让HTTP处理函数解析请求参数更方便。
|
||||
|
||||
首先,我們看看如何使用它。下面的search函數是一個HTTP請求處理函數。它定義了一個匿名結構體類型的變量,用結構體的每個成員表示HTTP請求的參數。其中結構體成員標籤指明了對於請求參數的名字,爲了減少URL的長度這些參數名通常都是神祕的縮略詞。Unpack將請求參數填充到合適的結構體成員中,這樣我們可以方便地通過合適的類型類來訪問這些參數。
|
||||
首先,我们看看如何使用它。下面的search函数是一个HTTP请求处理函数。它定义了一个匿名结构体类型的变量,用结构体的每个成员表示HTTP请求的参数。其中结构体成员标签指明了对于请求参数的名字,为了减少URL的长度这些参数名通常都是神秘的缩略词。Unpack将请求参数填充到合适的结构体成员中,这样我们可以方便地通过合适的类型类来访问这些参数。
|
||||
|
||||
<u><i>gopl.io/ch12/search</i></u>
|
||||
```Go
|
||||
@@ -28,9 +28,9 @@ func search(resp http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
```
|
||||
|
||||
下面的Unpack函數主要完成三件事情。第一,它調用req.ParseForm()來解析HTTP請求。然後,req.Form將包含所有的請求參數,不管HTTP客戶端使用的是GET還是POST請求方法。
|
||||
下面的Unpack函数主要完成三件事情。第一,它调用req.ParseForm()来解析HTTP请求。然后,req.Form将包含所有的请求参数,不管HTTP客户端使用的是GET还是POST请求方法。
|
||||
|
||||
下一步,Unpack函數將構建每個結構體成員有效參數名字到成員變量的映射。如果結構體成員有成員標籤的話,有效參數名字可能和實際的成員名字不相同。reflect.Type的Field方法將返迴一個reflect.StructField,里面含有每個成員的名字、類型和可選的成員標籤等信息。其中成員標籤信息對應reflect.StructTag類型的字符串,併且提供了Get方法用於解析和根據特定key提取的子串,例如這里的http:"..."形式的子串。
|
||||
下一步,Unpack函数将构建每个结构体成员有效参数名字到成员变量的映射。如果结构体成员有成员标签的话,有效参数名字可能和实际的成员名字不相同。reflect.Type的Field方法将返回一个reflect.StructField,里面含有每个成员的名字、类型和可选的成员标签等信息。其中成员标签信息对应reflect.StructTag类型的字符串,并且提供了Get方法用于解析和根据特定key提取的子串,例如这里的http:"..."形式的子串。
|
||||
|
||||
<u><i>gopl.io/ch12/params</i></u>
|
||||
```Go
|
||||
@@ -78,9 +78,9 @@ func Unpack(req *http.Request, ptr interface{}) error {
|
||||
}
|
||||
```
|
||||
|
||||
最後,Unpack遍歷HTTP請求的name/valu參數鍵值對,併且根據更新相應的結構體成員。迴想一下,同一個名字的參數可能出現多次。如果發生這種情況,併且對應的結構體成員是一個slice,那麽就將所有的參數添加到slice中。其它情況,對應的成員值將被覆蓋,隻有最後一次出現的參數值才是起作用的。
|
||||
最后,Unpack遍历HTTP请求的name/valu参数键值对,并且根据更新相应的结构体成员。回想一下,同一个名字的参数可能出现多次。如果发生这种情况,并且对应的结构体成员是一个slice,那么就将所有的参数添加到slice中。其它情况,对应的成员值将被覆盖,只有最后一次出现的参数值才是起作用的。
|
||||
|
||||
populate函數小心用請求的字符串類型參數值來填充單一的成員v(或者是slice類型成員中的單一的元素)。目前,它僅支持字符串、有符號整數和布爾型。其中其它的類型將留做練習任務。
|
||||
populate函数小心用请求的字符串类型参数值来填充单一的成员v(或者是slice类型成员中的单一的元素)。目前,它仅支持字符串、有符号整数和布尔型。其中其它的类型将留做练习任务。
|
||||
|
||||
```Go
|
||||
func populate(v reflect.Value, value string) error {
|
||||
@@ -109,7 +109,7 @@ func populate(v reflect.Value, value string) error {
|
||||
}
|
||||
```
|
||||
|
||||
如果我們上上面的處理程序添加到一個web服務器,則可以産生以下的會話:
|
||||
如果我们上上面的处理程序添加到一个web服务器,则可以产生以下的会话:
|
||||
|
||||
```
|
||||
$ go build gopl.io/ch12/search
|
||||
@@ -128,8 +128,8 @@ $ ./fetch 'http://localhost:12345/search?q=hello&max=lots'
|
||||
max: strconv.ParseInt: parsing "lots": invalid syntax
|
||||
```
|
||||
|
||||
**練習 12.11:** 編寫相應的Pack函數,給定一個結構體值,Pack函數將返迴合併了所有結構體成員和值的URL。
|
||||
**练习 12.11:** 编写相应的Pack函数,给定一个结构体值,Pack函数将返回合并了所有结构体成员和值的URL。
|
||||
|
||||
**練習 12.12:** 擴展成員標籤以表示一個請求參數的有效值規則。例如,一個字符串可以是有效的email地址或一個信用卡號碼,還有一個整數可能需要是有效的郵政編碼。脩改Unpack函數以檢査這些規則。
|
||||
**练习 12.12:** 扩展成员标签以表示一个请求参数的有效值规则。例如,一个字符串可以是有效的email地址或一个信用卡号码,还有一个整数可能需要是有效的邮政编码。修改Unpack函数以检查这些规则。
|
||||
|
||||
**練習 12.13:** 脩改S表達式的編碼器(§12.4)和解碼器(§12.6),采用和encoding/json包(§4.5)類似的方式使用成員標籤中的sexpr:"..."字串。
|
||||
**练习 12.13:** 修改S表达式的编码器(§12.4)和解码器(§12.6),采用和encoding/json包(§4.5)类似的方式使用成员标签中的sexpr:"..."字串。
|
||||
|
||||
Reference in New Issue
Block a user