Dalam Go, medan struct tanpa nama lazimnya disusun seolah-olah medan yang dieksport dalamannya ialah medan dalam struct luar. Walau bagaimanapun, ini boleh membawa kepada tingkah laku yang tidak dijangka apabila menyusun struct dengan ahli tanpa nama jenis antara muka{}.
Pertimbangkan contoh berikut:
<code class="go">type User struct { Id int `json:"id"` Name string `json:"name"` } type Session struct { Id int `json:"id"` UserId int `json:"userId"` } type Anything interface{} type Hateoas struct { Anything Links map[string]string `json:"_links"` } func MarshalHateoas(subject interface{}) ([]byte, error) { h := &Hateoas{subject, make(map[string]string)} switch s := subject.(type) { case *User: h.Links["self"] = fmt.Sprintf("http://user/%d", s.Id) case *Session: h.Links["self"] = fmt.Sprintf("http://session/%d", s.Id) } return json.MarshalIndent(h, "", " ") } func main() { u := &User{123, "James Dean"} s := &Session{456, 123} json, err := MarshalHateoas(u) if err != nil { panic(err) } else { fmt.Println("User JSON:") fmt.Println(string(json)) } json, err = MarshalHateoas(s) if err != nil { panic(err) } else { fmt.Println("Session JSON:") fmt.Println(string(json)) } }</code>
Apabila berjalan kod ini, JSON yang terhasil tidak seperti yang dijangkakan:
<code class="json">User JSON: { "Anything": { "id": 123, "name": "James Dean" }, "_links": { "self": "http://user/123" } } Session JSON: { "Anything": { "id": 456, "userId": 123 }, "_links": { "self": "http://session/456" } }</code>
Seperti yang anda lihat, ahli tanpa nama Anything dianggap sebagai medan bernama dalam JSON, yang bukan tingkah laku yang dimaksudkan.
Untuk meratakan ahli tanpa nama dan mencapai struktur JSON yang diingini, kita boleh menggunakan pakej reflect untuk menggelungkan medan struct dan memetakannya ke peta[rentetan]antara muka{}. Ini membolehkan kami mengekalkan struktur rata bagi struktur asal tanpa memperkenalkan medan baharu.
Kod yang dikemas kini adalah seperti berikut:
<code class="go">import ( "encoding/json" "fmt" "reflect" ) // ... (rest of the code remains the same) func MarshalHateoas(subject interface{}) ([]byte, error) { links := make(map[string]string) out := make(map[string]interface{}) subjectValue := reflect.Indirect(reflect.ValueOf(subject)) subjectType := subjectValue.Type() for i := 0; i < subjectType.NumField(); i++ { field := subjectType.Field(i) name := subjectType.Field(i).Name out[field.Tag.Get("json")] = subjectValue.FieldByName(name).Interface() } switch s := subject.(type) { case *User: links["self"] = fmt.Sprintf("http://user/%d", s.Id) case *Session: links["self"] = fmt.Sprintf("http://session/%d", s.Id) } out["_links"] = links return json.MarshalIndent(out, "", " ") }</code>
Dengan pengubahsuaian ini, JSON yang terhasil diratakan dengan betul:
<code class="json">User JSON: { "id": 123, "name": "James Dean", "_links": { "self": "http://user/123" } } Session JSON: { "id": 456, "userId": 123, "_links": { "self": "http://session/456" } }</code>
Atas ialah kandungan terperinci Bagaimana untuk Meratakan Medan Antara Muka Tanpa Nama dalam Pensirian Go JSON?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!