W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
項目中我們經(jīng)常會遇到大量?struct
?的使用,以及各種數(shù)據(jù)類型到?struct
?的轉(zhuǎn)換/賦值(特別是?json/xml
?/各種協(xié)議編碼轉(zhuǎn)換)。為提高編碼及項目維護效率,?gconv
?模塊為各位開發(fā)者帶來了極大的福利,為數(shù)據(jù)解析提供了更高的靈活度。
?gconv
?模塊通過?Struct
?轉(zhuǎn)換方法執(zhí)行?struct
?類型轉(zhuǎn)換,其定義如下:
// Struct maps the params key-value pairs to the corresponding struct object's attributes.
// The third parameter `mapping` is unnecessary, indicating the mapping rules between the
// custom key name and the attribute name(case sensitive).
//
// Note:
// 1. The `params` can be any type of map/struct, usually a map.
// 2. The `pointer` should be type of *struct/**struct, which is a pointer to struct object
// or struct pointer.
// 3. Only the public attributes of struct object can be mapped.
// 4. If `params` is a map, the key of the map `params` can be lowercase.
// It will automatically convert the first letter of the key to uppercase
// in mapping procedure to do the matching.
// It ignores the map key, if it does not match.
func Struct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error)
其中:
params
?為需要轉(zhuǎn)換到?struct
?的變量參數(shù),可以為任意數(shù)據(jù)類型,常見的數(shù)據(jù)類型為?map
?。pointer
?為需要執(zhí)行轉(zhuǎn)的目標(biāo)?struct
?對象,這個參數(shù)必須為該?struct
?的對象指針,轉(zhuǎn)換成功后該對象的屬性將會更新。mapping
?為自定義的?map
?鍵名到?strcut
?屬性之間的映射關(guān)系,此時?params
?參數(shù)必須為?map
?類型,否則該參數(shù)無意義。大部分場景下使用可以不用提供該參數(shù),直接使用默認(rèn)的轉(zhuǎn)換規(guī)則即可。更多的?struct
?相關(guān)轉(zhuǎn)換方法請參考接口文檔:https://pkg.go.dev/github.com/gogf/gf/v2/util/gconv
?gconv
?模塊的?struct
?轉(zhuǎn)換特性非常強大,支持任意數(shù)據(jù)類型到?struct
?屬性的映射轉(zhuǎn)換。在沒有提供自定義?mapping
?轉(zhuǎn)換規(guī)則的情況下,默認(rèn)的轉(zhuǎn)換規(guī)則如下:
struct
?中需要匹配的屬性必須為 公開屬性 (首字母大寫)。params
?類型的不同,邏輯會有不同:params
?參數(shù)類型為?map
?:鍵名會自動按照 不區(qū)分大小寫 且 忽略特殊字符 的形式與?struct
?屬性進行匹配。params
?參數(shù)為其他類型:將會把該變量值與?struct
?的第一個屬性進行匹配。struct
?的屬性為復(fù)雜數(shù)據(jù)類型如?slice
?,?map
?,?strcut
?那么會進行遞歸匹配賦值。以下是幾個?map
?鍵名與?struct
?屬性名稱的示例:
map鍵名 struct屬性 是否匹配
name Name match
Email Email match
nickname NickName match
NICKNAME NickName match
Nick-Name NickName match
nick_name NickName match
nick name NickName match
NickName Nick_Name match
Nick-name Nick_Name match
nick_name Nick_Name match
nick name Nick_Name match
當(dāng)給定的?pointer
?參數(shù)類型為?**struct
?時,?Struct
?方法內(nèi)部將會自動創(chuàng)建該?struct
?對象,并修改傳遞變量指向的指針地址。
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
func main() {
type User struct {
Uid int
Name string
}
params := g.Map{
"uid": 1,
"name": "john",
}
var user *User
if err := gconv.Struct(params, &user); err != nil {
panic(err)
}
g.Dump(user)
}
執(zhí)行后,輸出結(jié)果為:
{
"Name": "john",
"Uid": 1
}
遞歸轉(zhuǎn)換是指當(dāng)?struct
?對象包含子對象時,并且子對象是?embedded
?方式定義時,可以將?params
?參數(shù)數(shù)據(jù)(第一個參數(shù))同時遞歸地映射到其子對象上,常用于帶有繼承對象的?struct
?上。
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
func main() {
type Ids struct {
Id int `json:"id"`
Uid int `json:"uid"`
}
type Base struct {
Ids
CreateTime string `json:"create_time"`
}
type User struct {
Base
Passport string `json:"passport"`
Password string `json:"password"`
Nickname string `json:"nickname"`
}
data := g.Map{
"id" : 1,
"uid" : 100,
"passport" : "john",
"password" : "123456",
"nickname" : "John",
"create_time" : "2019",
}
user := new(User)
gconv.Struct(data, user)
g.Dump(user)
}
執(zhí)行后,終端輸出結(jié)果為:
{
"Base": {
"id": 1,
"uid": 100,
"create_time": "2019"
},
"nickname": "John",
"passport": "john",
"password": "123456"
}
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
type User struct {
Uid int
Name string
SiteUrl string
NickName string
Pass1 string `c:"password1"`
Pass2 string `c:"password2"`
}
func main() {
var user *User
// 使用默認(rèn)映射規(guī)則綁定屬性值到對象
user = new(User)
params1 := g.Map{
"uid": 1,
"Name": "john",
"site_url": "https://goframe.org",
"nick_name": "johng",
"PASS1": "123",
"PASS2": "456",
}
if err := gconv.Struct(params1, user); err == nil {
g.Dump(user)
}
// 使用struct tag映射綁定屬性值到對象
user = new(User)
params2 := g.Map{
"uid": 2,
"name": "smith",
"site-url": "https://goframe.org",
"nick name": "johng",
"password1": "111",
"password2": "222",
}
if err := gconv.Struct(params2, user); err == nil {
g.Dump(user)
}
}
可以看到,我們可以直接通過?Struct
?方法將?map
?按照默認(rèn)規(guī)則綁定到?struct
?上,也可以使用?struct tag
?的方式進行靈活的設(shè)置。此外,?Struct
?方法有第三個?map
?參數(shù),用于指定自定義的參數(shù)名稱到屬性名稱的映射關(guān)系。
執(zhí)行后,輸出結(jié)果為:
{
"Uid": 1,
"Name": "john",
"SiteUrl": "https://goframe.org",
"NickName": "johng",
"Pass1": "123",
"Pass2": "456"
}
{
"Uid": 2,
"Name": "smith",
"SiteUrl": "https://goframe.org",
"NickName": "johng",
"Pass1": "111",
"Pass2": "222"
}
屬性支持?struct
?對象或者?struct
?對象指針(目標(biāo)為指針且未?nil
?時,轉(zhuǎn)換時會自動初始化)轉(zhuǎn)換。
package main
import (
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/frame/g"
"fmt"
)
func main() {
type Score struct {
Name string
Result int
}
type User1 struct {
Scores Score
}
type User2 struct {
Scores *Score
}
user1 := new(User1)
user2 := new(User2)
scores := g.Map{
"Scores": g.Map{
"Name": "john",
"Result": 100,
},
}
if err := gconv.Struct(scores, user1); err != nil {
fmt.Println(err)
} else {
g.Dump(user1)
}
if err := gconv.Struct(scores, user2); err != nil {
fmt.Println(err)
} else {
g.Dump(user2)
}
}
執(zhí)行后,輸出結(jié)果為:
{
"Scores": {
"Name": "john",
"Result": 100
}
}
{
"Scores": {
"Name": "john",
"Result": 100
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: