2011-06-18 13 views
63

reflect पैकेज का उपयोग कर संरचना फ़ील्ड के साथ काम करने में कोई कठिन समय नहीं है। विशेष रूप से, यह पता नहीं लगाया गया है कि फ़ील्ड मान कैसे सेट करें।प्रतिबिंबित करने का उपयोग करके, आप संरचना फ़ील्ड का मान कैसे सेट करते हैं?

 
type t struct { fi int; fs string } 
var r t = t{ 123, "jblow" } 
var i64 int64 = 456 
  1. क्षेत्र का नाम हो रही है मैं - यह एक के रूप में मैदान के

    var field = reflect.TypeOf(r).Field(i).Name

  2. हो रही मूल्य मैं काम करने के लिए) इंटरफेस {} लगता है, ख) पूर्णांक - यह काम करने के लिए लगता है

    var iface interface{} = reflect.ValueOf(r).Field(i).Interface()

    क्षेत्र के

  3. सेटिंग मूल्य मैं - एक कोशिश - आतंक

    reflect.ValueOf(r).Field(i).SetInt(i64)

    आतंक: reflect.Value · SetInt मूल्य का उपयोग कर unexported क्षेत्र

    का उपयोग कर इसे मानते हुए क्षेत्र पसंद नहीं आया प्राप्त नाम "आईडी" और "नाम", इसलिए इसका नाम बदलकर "आईडी" और "नाम"

    ए) क्या यह धारणा सही है?

    ख) यदि सही है, एक ही फाइल/पैकेज में के बाद से आवश्यक नहीं सोचा था कि क्षेत्र के

  4. सेटिंग मूल्य मैं - कोशिश दो (फ़ील्ड नाम पूंजीकृत के साथ) - आतंक

    reflect.ValueOf(r).Field(i).SetInt(465)

    reflect.ValueOf(r).Field(i).SetInt(i64)

    आतंक: reflect.Value · SetInt unaddressable मूल्य

  5. का उपयोग कर

@peterSO द्वारा निर्देश नीचे पूरी तरह से और उच्च गुणवत्ता

चार कर रहे हैं। इस काम करता है:

reflect.ValueOf(&r).Elem().Field(i).SetInt(i64)

वह भी दस्तावेजों कि फ़ील्ड नाम निर्यात नहीं किया जा चाहिए

+0

निकटतम उदाहरण जो मैं ढूंढ सकता था डेटा सेट करने के लिए 'प्रतिबिंबित' का उपयोग करने वाला कोई व्यक्ति http://comments.gmane.org/gmane.comp.lang.go.general/35045 था, लेकिन यहां तक ​​कि वहां उन्होंने वास्तविक गंदे काम करने के लिए 'json.Unmarshal' का उपयोग किया –

+0

(उपर्युक्त टिप्पणी अप्रचलित है) –

उत्तर

93

जाओ open source code रूप में उपलब्ध है (बड़े अक्षर से शुरू)। प्रतिबिंब के बारे में जानने का एक अच्छा तरीका यह देखना है कि कोर गो डेवलपर्स इसका उपयोग कैसे करते हैं। उदाहरण के लिए, जाओ fmt और json पैकेज। पैकेज प्रलेखन में हेडिंग पैकेज फ़ाइलों के तहत स्रोत कोड फ़ाइलों के लिंक हैं।

गो जेसन पैकेज मार्शल और अनारशल्स JSON से और जाने के लिए संरचनाएं।


यहाँ एक चरण-दर-चरण उदाहरण है जो एक struct फ़ील्ड का मान सेट करते समय सावधानी से त्रुटियों से परहेज है।

गो reflect पैकेज में CanAddr फ़ंक्शन है।

func (v Value) CanAddr() bool 

CanAddr TRUE देता मूल्य के पते के प के साथ प्राप्त किया जा सकता। ऐसे मूल्यों को पता योग्य कहा जाता है। मान पता योग्य है यदि यह स्लाइस के तत्व है, एड्रेस करने योग्य सरणी का एक तत्व, एड्रेस करने योग्य स्ट्रक्चर का एक क्षेत्र, या का परिणाम एक सूचक को संदर्भित करना है। यदि CanAddr गलत लौटाता है, तो कॉलर आतंक को कॉल करेगा।

जाओ reflect पैकेज एक CanSet समारोह है, जो, अगर true, संकेत मिलता है कि CanAddr भी true है।

func (v Value) CanSet() bool 

CanSet TRUE देता वी का मूल्य बदला जा सकता है। एक मान केवल तभी बदला जा सकता है जब यह पता योग्य है और अप्रत्याशित संरचना फ़ील्ड के उपयोग से प्राप्त नहीं किया गया था। यदि कैनसेट झूठा लौटाता है, तो सेट या किसी भी टाइप-विशिष्ट सेटर (उदा।, सेटबूल, SetInt64) कॉलिंग घबराएगा।

हमें यकीन है कि हम struct क्षेत्र Set कर सकते हैं बनाने की जरूरत है। उदाहरण के लिए,

package main 

import (
    "fmt" 
    "reflect" 
) 

func main() { 
    type t struct { 
     N int 
    } 
    var n = t{42} 
    // N at start 
    fmt.Println(n.N) 
    // pointer to struct - addressable 
    ps := reflect.ValueOf(&n) 
    // struct 
    s := ps.Elem() 
    if s.Kind() == reflect.Struct { 
     // exported field 
     f := s.FieldByName("N") 
     if f.IsValid() { 
      // A Value can be changed only if it is 
      // addressable and was not obtained by 
      // the use of unexported struct fields. 
      if f.CanSet() { 
       // change value of N 
       if f.Kind() == reflect.Int { 
        x := int64(7) 
        if !f.OverflowInt(x) { 
         f.SetInt(x) 
        } 
       } 
      } 
     } 
    } 
    // N at end 
    fmt.Println(n.N) 
} 

Output: 
42 
7 

हम कुछ है कि सभी त्रुटि जाँच अनावश्यक हैं हो सकता है अगर, उदाहरण के सरल करने के लिए,

package main 

import (
    "fmt" 
    "reflect" 
) 

func main() { 
    type t struct { 
     N int 
    } 
    var n = t{42} 
    fmt.Println(n.N) 
    reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7) 
    fmt.Println(n.N) 
} 
+0

अब वहां जा रहे हैं –

+2

छोड़ दो! कहीं कहीं जवाब है, लेकिन जेसन पीकेजी पर चार घंटे के काम ने मुझे यह नहीं दिया है। प्रतिबिंबित पीकेजी, खींचने की जानकारी बहुत सीधी है, लेकिन डेटा सेट करने के लिए कुछ काले जादू की आवश्यकता होती है जिसके लिए मुझे कहीं एक साधारण उदाहरण देखना अच्छा लगेगा! –

+2

बकाया! यदि आप थाईलैंड में कभी भी हैं तो कृपया मुझे आपको एक बियर या दो या तीन के साथ इलाज करने दें! बहुत बहुत धन्यवाद –

6

यह काम करने के लिए लगता है:

package main 

import (
    "fmt" 
    "reflect" 
) 

type Foo struct { 
    Number int 
    Text string 
} 

func main() { 
    foo := Foo{123, "Hello"} 

    fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) 

    reflect.ValueOf(&foo).Elem().Field(0).SetInt(321) 

    fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) 
} 

प्रिंटों:

123 
321 
+0

धन्यवाद! अब मैंने पीटरसेओ के नोट्स पढ़े हैं, यह सही समझ में आता है। मैं foo का उपयोग कर रहा था, नहीं और foo, इसलिए बदला नहीं जा सका, और यह सुनिश्चित नहीं था कि Elem() क्या था। –

संबंधित मुद्दे