2016-08-13 14 views
5

गो में, मैं ऐसा कुछ करना चाहता हूं। मेरे पास कई structs के साथ एक बड़ी वस्तु है (Google के protobuf का उपयोग करके)। यहां एक संक्षिप्त उदाहरण है:गोलांग गतिशील चर संदर्भ

person.name = "testing" 
person.address.street = "123 test st" 
person.address.city = "tester" 
person.address.zip = 90210 
person.billing.address.same = true 

मैं गतिशील रूप से चीजों का संदर्भ देने में सक्षम होना चाहता हूं। उदाहरण के लिए:

key := "person.address.zip" 
fmt.Println("the value of key: " + key) // would like to get 90210 
key := "person.address.city" 
fmt.Println("the value of key: " + key) // would like to get "tester" 

क्या यह संभव है? यदि हां, तो मैं यह कैसे कर सकता हूं? अनिवार्य रूप से, मैं एक रिपोर्ट बना रहा हूं जिसमें केवल ऑब्जेक्ट का उप-समूह शामिल है और मैं एक मैपिंग फ़ाइल बनाने में सक्षम होना चाहता हूं जहां उपयोगकर्ता एक साथ कुंजी/मान मैप कर सकता है और मेरा प्रोग्राम मूल्य को आउटपुट करेगा। मैं अजगर में इस काम की है, लेकिन आप reflect पैकेज से func (v Value) FieldByName(name string) Value उपयोग कर सकते हैं जाओ का उपयोग कर :)

+0

हां, यह संभव है। यह आपको पैकेज प्रतिबिंब प्रदान करता है। प्रतिबिंब का नुकसान आम तौर पर काम की बड़ी मात्रा है। दूसरी ओर - प्रतिबिंबित किए बिना ऐसे परिपूर्ण पैकेज जैसे HTML/टेम्पलेट या टेक्स्ट/टेम्पलेट नहीं लिखा जा सकता है, जहां लेखन की शैली व्याख्या की गई भाषा (जैसे पायथन) की तरह है, हालांकि संकलित किया गया है। – lofcek

+0

और प्रतिबिंब धीमा है, अंतिम उपाय होना चाहिए। – OneOfOne

+4

यदि आपको वास्तव में इस तरह की कुछ ज़रूरत है, तो आपको (नेस्टेड) ​​मानचित्रों का उपयोग करना चाहिए, न कि संरचना मूल्यों के पदानुक्रम। – kostix

उत्तर

4

कोशिश करना चाहता था:

FieldByName दिए गए नाम के साथ struct क्षेत्र देता है। यह शून्य मान देता है यदि कोई फ़ील्ड नहीं मिला है। यह पैनिक्स अगर वी के प्रकार संरचना नहीं है।

इस काम के नमूना कोड की तरह:

package main 

import "fmt" 
import "reflect" 

func main() { 
    person := Person{} 
    person.name = "testing" 
    person.address.street = "123 test st" 
    person.address.city = "tester" 
    person.address.zip = 90210 
    person.billing.address.same = true 

    v := reflect.ValueOf(person) 
    f := v.FieldByName("address") 
    key := f.FieldByName("zip") 
    fmt.Println(key)     // 90210 
    fmt.Println(f.FieldByName("city")) // tester  
} 

type Person struct { 
    name string 
    address Address 
    billing Billing 
} 
type Billing struct { 
    address Address 
} 
type Address struct { 
    street, city string 
    zip   int 
    same   bool 
} 

उत्पादन:

90210 
tester 

और अपने विशेष मामले के लिए, आप fmt.Println(field(person, "person.address.zip")) उपयोग कर सकते हैं, इस काम के नमूना कोड की तरह (बस के लिए प्रदर्शन):

package main 

import "fmt" 
import "reflect" 
import "strings" 

func field(t interface{}, key string) reflect.Value { 
    strs := strings.Split(key, ".") 
    v := reflect.ValueOf(t) 
    for _, s := range strs[1:] { 
     v = v.FieldByName(s) 
    } 
    return v 
} 
func main() { 
    person := Person{} 
    person.name = "testing" 
    person.address.street = "123 test st" 
    person.address.city = "tester" 
    person.address.zip = 90210 
    person.billing.address.same = true 

    fmt.Println(field(person, "person.address.zip")) //90210 
    fmt.Println(field(person, "person.address.city")) //tester 
} 

type Person struct { 
    name string 
    address Address 
    billing Billing 
} 
type Billing struct { 
    address Address 
} 
type Address struct { 
    street, city string 
    zip   int 
    same   bool 
} 

उत्पादन:

90210 
tester 
1

मैं Protobuf के internals से परिचित नहीं हूँ या ऐसा करने के लिए करता है, तो यह किसी भी साधन प्रदान करता है।

लेकिन, (1) आप जिस तरह से आप वर्णित में मूल्य पढ़ना पसंद करता है, तो - गतिशील और खेतों चेनिंग द्वारा (2) आप इसे एक से अधिक समय में पढ़ना चाहते हैं; मैं इसे जेसन में क्रमबद्ध करता हूं और this पैकेज का उपयोग करता हूं। यह बहुत तेज़ है और आपको वही अर्थपूर्ण वांछित देता है:

// assuming your object got marshaled to this for example 
json := `{"name":{"first":"Janet","last":"Prichard"},"age":47}` 
value := gjson.Get(json, "name.last") 
println(value.String()) 
संबंधित मुद्दे