<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## Go中的結構體標簽和反射 反射是一個復雜的話題。在Go中反射最常用在處理結構體標簽,其核心是處理鍵值字符串。即查找鍵,然后處理對應值。可以想象,在使用JSON marshal和unmarshal進行操作的時候,處理這些值存在很多復雜性。 反射包用于解析接口對象。它能夠幫助我們查看結構類型,值,結構標簽等。如果你需要處理的不僅僅是基本類型轉換,那么這你應該關注reflect包的使用。 ### 實踐 1. 創建serialize.go: ``` func SerializeStructStrings(s interface{}) (string, error) { result := "" // reflect.TypeOf使用傳入的接口生成type類型 r := reflect.TypeOf(s) // reflect.ValueOf返回結構體每個字段對應的值 value := reflect.ValueOf(s) // 如果傳入的是個結構體的指針 那么可以針對性的對其進行單獨處理 if r.Kind() == reflect.Ptr { r = r.Elem() value = value.Elem() } // 循環所有的內部字段 for i := 0; i < r.NumField(); i++ { field := r.Field(i) // 字段的名稱 key := field.Name // Lookup返回與標記字符串中的key關聯的值。 如果密鑰存在于標記中,則返回值(可以為空)。 // 否則返回的值將是空字符串。ok返回值報告是否在標記字符串中顯式設置了值。 // 如果標記沒有傳統格式,則Lookup返回的值不做指定。 if serialize, ok := field.Tag.Lookup("serialize"); ok { // 忽略“ - ”否則整個值成為序列化'鍵' if serialize == "-" { continue } key = serialize } // 判斷每個字段的類型 switch value.Field(i).Kind() { // 當前示例我們僅簡單判斷字符串 case reflect.String: result += key + ":" + value.Field(i).String() + ";" default: continue } } return result, nil } ``` 2. 建立deserialize.go : ``` package tags import ( "errors" "reflect" "strings" ) // DeSerializeStructStrings 反序列化字符串為對應的結構體 func DeSerializeStructStrings(s string, res interface{}) error { r := reflect.TypeOf(res) // 我們要求傳入的必須是指針 if r.Kind() != reflect.Ptr { return errors.New("res must be a pointer") } // 解指針 // Elem返回r(Type類型)元素的type // 如果該type.Kind不是Array, Chan, Map, Ptr, 或 Slice會產生panic r = r.Elem() value := reflect.ValueOf(res).Elem() // 將傳入的序列化字符串分割為map vals := strings.Split(s, ";") valMap := make(map[string]string) for _, v := range vals { keyval := strings.Split(v, ":") if len(keyval) != 2 { continue } valMap[keyval[0]] = keyval[1] } // 循環所有的內部字段 for i := 0; i < r.NumField(); i++ { field := r.Field(i) // 檢查是否符合預置的tag if serialize, ok := field.Tag.Lookup("serialize"); ok { // 忽略'-'否則整個值成為序列化'鍵' if serialize == "-" { continue } // 判斷是否處于map內 if val, ok := valMap[serialize]; ok { value.Field(i).SetString(val) } } else if val, ok := valMap[field.Name]; ok { // 是否是在map中的字段名稱 value.Field(i).SetString(val) } } return nil } ``` 3. 建立 tags.go: ``` package tags import "fmt" // 注意Person內個字段的tag標簽 type Person struct { Name string `serialize:"name"` City string `serialize:"city"` State string Misc string `serialize:"-"` Year int `serialize:"year"` } // EmptyStruct 演示了根據 tag 序列化和反序列化一個空結構體 func EmptyStruct() error { p := Person{} res, err := SerializeStructStrings(&p) if err != nil { return err } fmt.Printf("Empty struct: %#v\n", p) fmt.Println("Serialize Results:", res) newP := Person{} if err := DeSerializeStructStrings(res, &newP); err != nil { return err } fmt.Printf("Deserialize results: %#v\n", newP) return nil } // FullStruct 演示了根據 tag 序列化和反序列化一個非空結構體 func FullStruct() error { p := Person{ Name: "Aaron", City: "Seattle", State: "WA", Misc: "some fact", Year: 2017, } res, err := SerializeStructStrings(&p) if err != nil { return err } fmt.Printf("Full struct: %#v\n", p) fmt.Println("Serialize Results:", res) newP := Person{} if err := DeSerializeStructStrings(res, &newP); err != nil { return err } fmt.Printf("Deserialize results: %#v\n", newP) return nil } ``` 4. 建立main.go: ``` package main import ( "fmt" "github.com/agtorre/go-cookbook/chapter3/tags" ) func main() { if err := tags.EmptyStruct(); err != nil { panic(err) } fmt.Println() if err := tags.FullStruct(); err != nil { panic(err) } } ``` 5. 這會輸出: ``` Empty struct: tags.Person{Name:"", City:"", State:"", Misc:"", Year:0} Serialize Results: name:;city:;State:; Deserialize results: tags.Person{Name:"", City:"", State:"", Misc:"", Year:0} Full struct: tags.Person{Name:"Aaron", City:"Seattle", State:"WA", Misc:"some fact", Year:2017} Serialize Results: name:Aaron;city:Seattle;State:WA; Deserialize results: tags.Person{Name:"Aaron", City:"Seattle", State:"WA", Misc:"", Year:0} ``` ### 說明 本節簡單的展示了使用反射根據結構體的tag標簽來進行字符串序列化和序列化,我們并未處理一些特殊情況,例如字符串包含 ':' 或 ';'。針對于本示例,需要注意: 1. 如果字段是字符串,則將對其進行序列化/反序列化。 2. 如果字段不是字符串,則將忽略該字段。 3. 如果字段的struct標記不包含"serialize",則需要進行額外操作以保證序列化/反序列化正確完成。 4. 沒有考慮處理重復項。 5. 如果未指定struct標記,則簡單使用字段名稱。 6. 如果指定了標簽為'-' ,則即使該字段是字符串,也會忽略。 還需要注意的是,反射不能與非導出值一起使用。 一個完善的反射操作需要考慮的細節很多,因此,在面對一個不是那么完美的第三方反射庫時,盡量保持仁慈之心是值得贊美的。 * * * * 學識淺薄,錯誤在所難免。歡迎在群中就本書提出修改意見,以饗后來者,長風拜謝。 Golang中國(211938256) beego實戰(258969317) Go實踐(386056972)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看