প্রতিবিম্ব ব্যবহার করে আপনি কীভাবে কোনও কাঠামোর ক্ষেত্রের মান সেট করবেন?


106

reflectপ্যাকেজ ব্যবহার করে স্ট্রাক্ট ফিল্ডগুলির সাথে কাজ করতে মোটামুটি সময় কাটাচ্ছে । ক্ষেত্রের মানটি কীভাবে সেট করবেন তা নির্দিষ্ট করে খুঁজে বের করতে পারেননি।

টাইপ টি স্ট্রাক্ট {ফাই ইন্ট; এফএস স্ট্রিং}
var rt = t {123, "jblow"}
var i64 int64 = 456
  1. ক্ষেত্রের নাম পাওয়া i - এটি কাজ করে বলে মনে হচ্ছে

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

  2. ক্ষেত্রের মান হ'ল ক) ইন্টারফেস {}, খ) ইনট - এটি কার্যকর বলে মনে হচ্ছে

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

    var i int = int(reflect.ValueOf(r).Field(i).Int())

  3. ক্ষেত্রের মান নির্ধারণ i - আতঙ্কিত one

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

    প্যানিক : রিফ্লেক্ট.ভ্যালু une অপরিবর্তিত ক্ষেত্র ব্যবহার করে প্রাপ্ত মান ব্যবহার করে সেট করুন

    ধরে নিলাম এটি ফিল্ডের নামগুলি "আইডি" এবং "নাম" পছন্দ করে না, সুতরাং "আইডি" এবং "নাম" নামকরণ করা হয়েছে

    ক) এই ধারণাটি কি সঠিক?

    খ) যদি সঠিক হয়, একই ফাইল / প্যাকেজ থেকে যেহেতু প্রয়োজন মনে করা যায় না

  4. ক্ষেত্রের মান নির্ধারণ i - দুটি চেষ্টা করুন (ক্ষেত্রের নাম মূলধন সহ) - আতঙ্কিত

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

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

    প্যানিক : রিফ্লেক্ট.ভ্যালু un অবসন্নযোগ্য মান ব্যবহার করে সেট করুন


@ পিটারএসও এর নীচে নির্দেশাবলী সম্পূর্ণ এবং উচ্চমানের are

চার। এইটা কাজ করে:

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

তিনি নথির পাশাপাশি ক্ষেত্রের নামগুলি রফতানিযোগ্য হতে হবে (মূল চিঠি দিয়ে শুরু করুন)


reflectডেটা সেট করার জন্য যে কারও কাছে আমি সবচেয়ে নিকটতম উদাহরণটি পেয়েছিলাম তা হ'ল মন্তব্য.gmane.org/gmane.comp.lang.go.general/35045 , কিন্তু সেখানেও তিনি json.Unmarshalআসল নোংরা কাজ করতেন
সিসি যুব

(উপরের মন্তব্যটি অপ্রচলিত)
সিসি তরুণ

উত্তর:


156

ওপেন সোর্স কোড হিসাবে গো পাওয়া যায় । রিফ্লেকশন সম্পর্কে জানার একটি ভাল উপায় হ'ল কোর গো বিকাশকারীরা কীভাবে এটি ব্যবহার করে। উদাহরণস্বরূপ, যান FMT এবং JSON প্যাকেজ। প্যাকেজ ডকুমেন্টেশনের প্যাকেজ ফাইলগুলির শিরোনামের অধীনে উত্স কোড ফাইলগুলির লিঙ্ক রয়েছে।

Go json প্যাকেজ মার্শাল এবং জেএসএন থেকে কাঠামোগত স্ট্রাকচার আনমারশাল করে।


এখানে ধাপে ধাপে উদাহরণ রয়েছে যা structসাবধানতার সাথে ত্রুটিগুলি এড়িয়ে চলাকালীন ক্ষেত্রের মান নির্ধারণ করে ।

গো reflectপ্যাকেজের একটি CanAddrফাংশন রয়েছে।

func (v Value) CanAddr() bool

CanAddr মানটির ঠিকানা অ্যাডারের সাথে প্রাপ্ত হতে পারলে সত্য ফিরে আসে। এ জাতীয় মানগুলিকে সম্বোধনযোগ্য বলা হয়। মানটি যদি ঠিকানা হিসাবে চিহ্নিত হয় তবে এটি যদি স্লাইসের উপাদান, ঠিকানাযোগ্য অ্যারের উপাদান, কোনও ঠিকানাযোগ্য কাঠামোর ক্ষেত্র বা কোনও পয়েন্টারকে অবচয় করার ফলাফল হয়। যদি CanAddr মিথ্যা ফেরত দেয় তবে অ্যাডারে কল করা আতঙ্কিত হবে।

গো reflectপ্যাকেজের একটি CanSetফাংশন রয়েছে, যা যদি trueবোঝায় যে CanAddrএটিও true

func (v Value) CanSet() bool

ক্যানসেট যদি সত্যিকার অর্থে ভি এর মান পরিবর্তন করা যায় তবে ফিরে আসে। একটি মান কেবল তখনই পরিবর্তন করা যায় যখন এটি ঠিকানাযোগ্য এবং অবিকৃত স্ট্রাক্ট ক্ষেত্রগুলির ব্যবহারের দ্বারা প্রাপ্ত না হয়েছিল। ক্যানসেট যদি মিথ্যা প্রত্যাবর্তন করে, কলিং সেট বা কোনও প্রকার-নির্দিষ্ট সেটার (যেমন, সেটবুল, সেটআইন্ট 64) আতঙ্কিত হবে।

আমরা নিশ্চিত আমরা পারি করতে হবে ক্ষেত্র। উদাহরণ স্বরূপ,Setstruct

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)
}

5
ছেড়ে দেত্তয়া! কোথাও কোথাও একটি উত্তর আছে, কিন্তু json pkg এ চার ঘন্টা কাজ করা আমার কাছে তা দেয়নি। রিফ্লেক্ট পিকেজি, তথ্য টানতে বেশ সোজা, তবে ডেটা সেট করার জন্য কিছু কালো যাদু প্রয়োজন যার জন্য আমি কোথাও একটি সাধারণ উদাহরণ দেখতে পছন্দ করব!
সিসি যুব

2
বিশিষ্ট! আপনি যদি কখনও থাইল্যান্ডে থাকেন তবে দয়া করে আমাকে আপনার একটি বিয়ার বা দু'ত তিনটি করে ট্রিট করুন! আপনাকে অনেক ধন্যবাদ
সিসি অল্প বয়স্ক

5
দুর্দান্ত ব্যবহারিক উদাহরণ, এই নিবন্ধটি আমার জন্য এটি সম্পূর্ণরূপে নির্মূল
ডানমাক্স

দুর্দান্ত উদাহরণ e
সারথ সাদাসিভান পিল্লাই

এটি কোনও কাঠামো ক্ষেত্র সেট করে না। এটি স্ট্রাক্টকে পয়েন্টারে একটি ক্ষেত্র সেট করে। স্পষ্টতই, এটি ওপি জিজ্ঞাসা করা প্রশ্নের উত্তর দিচ্ছে না।
wvxvw

13

এটি কাজ করে বলে মনে হচ্ছে:

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

ধন্যবাদ! এখন যেহেতু আমি পিটারসো এর নোটগুলি পড়েছি, এটি সঠিক ধারণা দেয়। আমি foo ব্যবহার করছিলাম, foo না, সুতরাং পরিবর্তন করা যায়নি, এবং এলেম () কী সম্পর্কে নিশ্চিত ছিলেন তা নিশ্চিত ছিল না।
সিসি অল্প বয়স্ক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.