亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go基于struct?tag實現(xiàn)結構體字段級別的訪問控制

 更新時間:2024年02月01日 14:28:31   作者:波羅學?碼途漫漫  
本文將會基于這個主題展開,討論Go中的結構體tag究竟是什么,我們該如何利用它,另外,文末還提供了一個實際案例,實現(xiàn)結構體字段級別的訪問,幫助我們進一步提升對struct tag的理解

struct tag 是什么?

在Go 中,結構體主要是用于定義復雜數(shù)據(jù)類型,而 struct tag 則是附加在 struct 字段后的字符串,提供了一種方式來存儲關于字段的元信息,然后,tag 在程序運行時一般不會直接影響程序邏輯,

如下是一個定義了 tag 的結構體 Person 類型。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

例子中,json:"name"json:"age" 就是結構體 tag。結構體 tag 的使用非常直觀。你只需要在定義結構體字段后,通過反引號 `` 包裹起來的鍵值對形式就可定義它們。

具體有什么用呢?

這個 tag 究竟有什么用呢?為何要定義它們。

單從這個例子中來看,假設你是在 "encoding/json" 庫中使用 Person 結構體,它是告訴 Go 在處理 JSON 序列化和反序列化時,字段名稱的轉化規(guī)則。

讓我們通過它在 "encoding/json" 的使用說明它的效果吧。

p := Person{Name: "John", Age: 30}
jsonData, err := json.Marshal(p)
if err != nil {
    log.Println(err)
}
fmt.Println(string(jsonData)) 

輸出:

{"name":"John","age":30}

可以看到輸出的 JSON 的 key 是 name 和 age,而非 Name 和 Age。

與其他語言對比的話,雖然 Go 的 struct tag 在某種程度上類似于 Java 的注解或 C# 的屬性,但 Go 的 tag 更加簡潔,并且主要通過反射機制在運行時被訪問。

這種設計反映了Go語言的哲學:簡單、直接而有效。但確實也是功能有限!

常見使用場景

結構體 tag 在 Go 語言中常見用途,我平時最常見有如下這些。

JSON/XML 序列反序列化

如前面的介紹的案例中,通過 encoding/json 或者其他的庫如 encoding/xml 庫,tag 可以控制如何將結構體字段轉換為 JSON 或 XML,或者如何從它們轉換回來。

數(shù)據(jù)庫操作

在ORM(對象關系映射)庫中,tag 可以定義數(shù)據(jù)庫表的列名、類型或其他特性。

如我們在使用 Gorm 時,會看到這樣的定義:

type User struct {
    gorm.Model
    Name   string `gorm:"type:varchar(100);unique_index"`
    Age    int    `gorm:"index:age"`
    Active bool   `gorm:"default:true"`
}

結構體 tag 可用于定義數(shù)據(jù)庫表的列名、類型或其他特性。

數(shù)據(jù)驗證

在一些庫中,tag 用于驗證數(shù)據(jù),例如,確保一個字段是有效的電子郵件地址。

如下是 govalidator[1] 使用結構體上 tag 實現(xiàn)定義數(shù)據(jù)驗證規(guī)則的一個案例。

type User struct {
    Email string `valid:"email"`
    Age   int    `valid:"range(18|99)"`
}

在這個例子中,valid tag 定義了字段的驗證規(guī)則,如 email 字段值是否是有效的 email,age 字段是否滿足數(shù)值在 18 到 99 之間等。

我們只要將類型為 User 類型的變量交給 govalidator,它可以根據(jù)這些規(guī)則來驗證數(shù)據(jù),確保數(shù)據(jù)的正確性和有效性。

示例如下:

valid, err := govalidator.ValidateStruct(User{Email: "test@example.com", Age: 20})

返回的 valid: 為 true 或 false,如果發(fā)生錯誤,err 提供具體的錯誤原因。

tag 行為自定義

前面展示的都是利用標準庫或三方庫提供的能力,如果想自定義 tag 該如何實現(xiàn)?畢竟有些情況下,如果默認提供的 tag 提供的能力不滿足需求,我們還是希望可以自定義 tag 的行為。

這需要了解與理解 Go 的反射機制,它為數(shù)據(jù)處理和元信息管理提供了強大的靈活性。

如下的示例代碼:

type Person struct {
    Name string `mytag:"MyName"`
}

t := reflect.TypeOf(Person{})
field, _ := t.FieldByName("Name")
fmt.Println(field.Tag.Get("mytag")) // 輸出: MyName

在這個例子中,我們的 Person 的字段 Name 有一個自定義的 tag - mytag,我們直接通過反射就可以訪問它。

這只是簡單的演示如何訪問到 tag。如何使用它呢?

這就要基于實際的場景了,當然,這通常也離不開與反射配合。下面我們來通過一個實際的例子介紹。

案例:結構體字段訪問控制

讓我們考慮一個實際的場景:一個結構訪問控制系統(tǒng)。

這個系統(tǒng)中,我們可以根據(jù)用戶的角色(如 admin、user)或者請求的來源(admin、web)控制對結構體字段的訪問。具體而言,假設我定義了一個包含敏感信息的結構體,我可以使用自定義 tag 來標記每個字段的訪問權限。

是不是想到,這或許可用在 API 接口范圍字段的控制上,防止泄露敏感數(shù)據(jù)給用戶。

接下來,具體看看如何做吧?

定義結構體

我們首先定義一個UserProfile結構體,其中包含用戶的各種信息。每個信息字段都有一個自定義的 access tag,用于標識字段訪問權限(adminuser)。

type UserProfile struct {
    Username    string `access:"user"`  // 所有用戶可見
    Email       string `access:"user"`  // 所有用戶可見
    PhoneNumber string `access:"admin"` // 僅管理員可見
    Address     string `access:"admin"` // 僅管理員可見
}

其中,PhoneNumber 和 Address 是敏感字段,它只對 admin 角色可見。而 UserName 和 Email 則是所有用戶可見。

到此,結構體 UserProfile 定義完成。

實現(xiàn)權限控制

接下來就是要實現(xiàn)一個函數(shù),實現(xiàn)根據(jù) UserProfile 定義的 access tag 決定字段內容的可見性。

假設函數(shù)名稱為 FilterFieldsByRole,它接受一個 UserProfile 類型變量和用戶角色,返回內容一個過濾后的 map(由 fieldname 到 fieldvalue 組成的映射),其中只包含角色有權訪問的字段。

func FilterFieldsByRole(profile UserProfile, role string) map[string]string {
    result := make(map[string]string)
    val := reflect.ValueOf(profile)
    typ := val.Type()

    for i := 0; i < val.NumField(); i++ {
        field := typ.Field(i)
        accessTag := field.Tag.Get("access")
        if accessTag == "user" || accessTag == role {
            // 獲取字段名稱
            fieldName := strings.ToLower(field.Name) 
            // 獲取字段值
            fieldValue := val.Field(i).String() 
            // 組織返回結果 result
            result[fieldName] = fieldValue
        }
    }
    return result
}

權限控制的重點邏輯部分,就是 if accessTag == "user" || accessTag == role 這段判斷條件。當滿足條件之后,接下來要做的就是通過反射獲取字段名稱和值,并組織目標的 Map 類變量 result了。

使用演示

讓我們來使用下 FilterFieldsByRole 函數(shù),檢查下是否滿足按角色訪問特定的用戶信息的功能。

示例代碼如下:

func main() {
    profile := UserProfile{
        Username:    "johndoe",
        Email:       "johndoe@example.com",
        PhoneNumber: "123-456-7890",
        Address:     "123 Elm St",
    }

    // 假設當前用戶是普通用戶
    userInfo := FilterFieldsByRole(profile, "user")
    fmt.Println(userInfo)

    // 假設當前用戶是管理員
    adminInfo := FilterFieldsByRole(profile, "admin")
    fmt.Println(adminInfo)
}

輸出:

map[username:johndoe email:johndoe@example.com]
map[username:johndoe email:johndoe@example.com phonenumber:123-456-7890 address:123 Elm St]

這個場景,通過自定義結構體 tag,給予指定角色,很輕松地就實現(xiàn)了一個基于角色的權限控制。

毫無疑問,這個代碼更加清晰和可維護,而且具有極大靈活性、擴展性。如果想擴展更多角色,也是更加容易。

不過還是要說明下,如果在 API 層面使用這樣的能力,還是要考慮反射可能帶來的性能影響。

總結

這篇博文介紹了Go語言中結構體 tag 的基礎知識,如是什么,如何使用。另外,還介紹了它們在不同場景下的應用。通過簡單的例子和對比,我們看到了 Go 中結構體 tag 的作用。

文章的最后,通過一個實際案例,演示了如何使用 struct tag 使我們代碼更加靈活強大。雖然 struct tag 的使用非常直觀,但正確地利用這些 tag 可以極大提升我們程序的功能和效率

引用鏈接

[1] govalidator: github.com/asaskevich/govalidator

以上就是Go基于struct tag實現(xiàn)結構體字段級別的訪問控制的詳細內容,更多關于Go struct tag訪問控制的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解go語言中type關鍵詞的幾種使用

    詳解go語言中type關鍵詞的幾種使用

    這篇文章主要介紹了詳解go語言中type的幾種使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • golang 中的 nil的場景分析

    golang 中的 nil的場景分析

    這篇文章主要介紹了golang 中的 nil,本文通過多種場景分析給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Golang執(zhí)行cmd命令行的方法

    Golang執(zhí)行cmd命令行的方法

    本文主要介紹了Golang執(zhí)行cmd命令行的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 深度解密Go語言中字符串的使用

    深度解密Go語言中字符串的使用

    在編程語言中,字符串發(fā)揮著重要的角色。這篇文章就來帶大家一起深度解密Go語言中的字符串,文中的示例代碼講解詳細,需要的可以參考一下
    2022-09-09
  • Go項目的目錄結構詳解

    Go項目的目錄結構詳解

    這篇文章主要介紹了Go項目的目錄結構,對基礎目錄做了講解,對項目開發(fā)中的其它目錄也一并做了介紹,需要的朋友可以參考下
    2014-10-10
  • Go實現(xiàn)Redis連接池方法

    Go實現(xiàn)Redis連接池方法

    為了更深入了解golang連接池的實現(xiàn),自已又重寫了一遍連接池。文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Golang+Vue輕松構建Web應用的方法步驟

    Golang+Vue輕松構建Web應用的方法步驟

    本文主要介紹了Golang+Vue輕松構建Web應用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • GoLand編寫 TCP 端口掃描器的詳細過程

    GoLand編寫 TCP 端口掃描器的詳細過程

    TCP,也就是傳輸控制協(xié)議(Transmission Control Protocol),這篇文章主要介紹了Go語言(Golang)編寫 TCP 端口掃描器,需要的朋友可以參考下
    2023-05-05
  • Go語言常用字符串處理方法實例匯總

    Go語言常用字符串處理方法實例匯總

    這篇文章主要介紹了Go語言常用字符串處理方法,實例匯總了Go語言中常見的各種字符串處理技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • Go處理包含多種引號的字符串的幾種方法

    Go處理包含多種引號的字符串的幾種方法

    在Go中,有幾種方式可以處理包含多種引號的字符串,以確保代碼的可讀性和正確性,本文將給大家詳細介紹了這幾種處理方式,并通過代碼示例講解的非常詳細,需要的朋友可以參考下
    2024-04-04

最新評論