ইন্টারফেস রূপান্তরকারী টুকরা টাইপ করুন


194

আমি কৌতূহল যে কেন গো সংক্ষিপ্ত রূপান্তর করবে []Tনা []interface{}যখন তা স্পষ্টত রূপান্তরিত Tহবে interface{}। এই রূপান্তরটি সম্পর্কে আমি কি কিছু মিস করছি তা মিস করছি?

উদাহরণ:

func foo([]interface{}) { /* do something */ }

func main() {
    var a []string = []string{"hello", "world"}
    foo(a)
}

go build অভিযোগ

ফাংশন আর্গুমেন্টে টাইপ [] ইন্টারফেস {as হিসাবে কোনও (টাইপ [] স্ট্রিং) ব্যবহার করতে পারে না

এবং যদি আমি স্পষ্টভাবে এটি করার চেষ্টা করি তবে একই জিনিস: b := []interface{}(a)অভিযোগ করে

একটি (টাইপ [] স্ট্রিং) [টাইপ [] ইন্টারফেসে রূপান্তর করতে পারে না {}

সুতরাং প্রতিবার যখনই এই রূপান্তরটি করা দরকার (যা অনেকটা সামনে আসবে বলে মনে হচ্ছে), আমি এরকম কিছু করছি:

b = make([]interface{}, len(a), len(a))
for i := range a {
    b[i] = a[i]
}

এই রূপান্তরগুলির সাথে সহায়তা করার জন্য এটি করার আরও ভাল উপায় বা স্ট্যান্ডার্ড গ্রন্থাগার রয়েছে? কোডের 4 টি অতিরিক্ত লাইন লিখতে যখনই আমি কোনও ফাংশনটি কল করতে চাইছি তবে এটি উদাহরণস্বরূপ অন্তর বা স্ট্রিংয়ের একটি তালিকা নিতে পারে বলে একধরনের নির্বোধ মনে হয়।


সুতরাং আপনি "একটি নতুন টুকরো বরাদ্দ এবং উপরের সমস্ত উপাদান অনুলিপি" বলতে "স্পষ্টভাবে [] টিকে [] ইন্টারফেস {}" তে রূপান্তরিত করেছেন। এটি "স্পষ্টভাবে টি ইন্টারফেস T}" তে রূপান্তরিত করার সাথে অসঙ্গত, যা আরও সাধারণ জড়িত স্ট্যাটিক ধরণের হিসাবে একই মানটির একটি দর্শন; কিছুই অনুলিপি করা হয় না; এবং যদি আপনি এটি টাইপ করে টি-তে টাইপ করেন তবে আপনি একই জিনিসটি আবার পাবেন back
newacct

1
এটি কীভাবে কার্যকর করা হবে সে সম্পর্কে খুব বেশি চিন্তাভাবনা করছিলেন না, কেবল উচ্চতর স্তরে জেনেরিক ধরণের না থাকার জন্য একটি সম্পূর্ণ তালিকাটিকে সহজেই অন্য ধরণের রূপান্তর করতে সক্ষম হওয়া সুবিধাজনক হবে।
ড্যানি

উত্তর:


215

গো-তে একটি সাধারণ নিয়ম রয়েছে যে সিনট্যাক্সগুলি জটিল / ব্যয়বহুল ক্রিয়াকলাপগুলি আড়াল করে না। রূপান্তর একটি stringএকটি থেকে interface{}হে (1) সময় সম্পন্ন করা হয়। রূপান্তর একটি []stringএকটি থেকে interface{}আরো হে মধ্যে সম্পন্ন করা হয় (1) সময় থেকে একটি ফালি এখনও এক মান। তবে, এটিকে একটিতে রূপান্তর []stringকরা []interface{}হল ও (এন) সময় কারণ স্লাইসের প্রতিটি উপাদান অবশ্যই একটিতে রূপান্তর করতে হবে interface{}

এই নিয়মের একটি ব্যতিক্রম স্ট্রিং রূপান্তরিত করা। stringএকটি []byteবা একটি থেকে এবং এ রূপান্তর করার সময় গোপনে []runeও (এন) কাজ করে যদিও রূপান্তরগুলি "সিনট্যাক্স" হয়।

এমন কোনও মানক গ্রন্থাগার নেই যা আপনার জন্য এই রূপান্তরটি করবে। আপনি প্রতিচ্ছবি দিয়ে একটি করতে পারেন, তবে এটি তিনটি লাইন বিকল্পের চেয়ে ধীর হবে।

প্রতিবিম্ব সহ উদাহরণ:

func InterfaceSlice(slice interface{}) []interface{} {
    s := reflect.ValueOf(slice)
    if s.Kind() != reflect.Slice {
        panic("InterfaceSlice() given a non-slice type")
    }

    ret := make([]interface{}, s.Len())

    for i:=0; i<s.Len(); i++ {
        ret[i] = s.Index(i).Interface()
    }

    return ret
}

যদিও আপনার সর্বোত্তম বিকল্পটি আপনার প্রশ্নে আপনি যে কোড দিয়েছেন তার রেখাগুলি ব্যবহার করা:

b := make([]interface{}, len(a))
for i := range a {
    b[i] = a[i]
}

3
এটি ধীর হতে পারে তবে এটি যে কোনও ধরণের টুকরো দিয়ে
উদারভাবে

এই পুরো উত্তরটি mapখুব বেশি বিটিডব্লিউতে প্রযোজ্য ।
রিকিয়া

এটি পাশাপাশি প্রযোজ্য channels
জাস্টিন ওহমস

সুস্পষ্ট ব্যাখ্যার জন্য ধন্যবাদ, সম্ভব হলে আপনি রেফ যোগ করতে পারেন। জন্য Converting a []string to an interface{} is also done in O(1) time?
ময়ূর

56

জিনিস আপনি অনুপস্থিত যে Tএবং interface{}যার একটি মান ঝুলিতে Tমেমরি বিভিন্ন উপস্থাপনা তাই জাভাস্ক্রিপ্টে গার্বেজ রূপান্তর করা যাবে না করেছি।

প্রকারের একটি পরিবর্তনশীল Tকেবল স্মৃতিতে এর মান। কোনও সম্পর্কিত ধরণের তথ্য নেই (Go এ প্রতিটি ভেরিয়েবলের একটি একক টাইপ রয়েছে যা রান টাইমের সময় নয় সংকলন সময়ে জানা যায়)। এটি এ জাতীয় স্মৃতিতে প্রতিনিধিত্ব করে:

  • মান

একটি interface{}অধিষ্ঠিত ধরনের একটি পরিবর্তনশীল Tভালো মেমরি প্রতিনিধিত্ব করা হয়

  • টাইপ পয়েন্টার T
  • মান

সুতরাং আপনার আসল প্রশ্নে ফিরে আসছেন: কেন স্পষ্টত রূপান্তরিত []Tহয় না []interface{}?

রূপান্তর []Tকরার []interface{}একটি নতুন ফালি তৈরি জড়িত করা হবে interface {}মান যা অ তুচ্ছ অপারেশন যেহেতু ইন-মেমোরি বিন্যাস সম্পূর্ণরূপে ভিন্ন।


10
এটি তথ্যবহুল এবং ভালভাবে লিখিত (+1), তবে আপনি তাঁর প্রশ্নের অন্য অংশটিকে সম্বোধন করছেন না: "এটি করার আরও ভাল উপায় কি আছে ..." (-1)।
weberc2

13

এখানে সরকারী ব্যাখ্যা: https://github.com/golang/go/wiki/InterfaceSlice

var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
    interfaceSlice[i] = d
}

ভাল তথ্য তবে এটি কোনও সরকারী ব্যাখ্যা নয়। এটি এমন একটি উইকি যেখানে প্রত্যেকে সম্পাদনা করতে পারে।
Inanc Gumus

[]interfaceআমি যে ধরণের প্রত্যাশা করি তার মধ্যে কীভাবে রূপান্তর করব []map[string]interface{}?
লুইস চ্যান

8

interface{}পরিবর্তে চেষ্টা করুন। স্লাইস হিসাবে ফিরে যেতে, চেষ্টা করুন

func foo(bar interface{}) {
    s := bar.([]string)
    // ...
}

3
এটি পরবর্তী প্রশ্নের জন্য দাঁড়ায়: ওপিকে কীভাবে পুনরাবৃত্তি করার কথা বলা হয় barযাতে এটি "কোনও ধরণের টুকরো" হিসাবে ব্যাখ্যা করে? নোট করুন যে তার থ্রি-লাইনারটি একটি []interface{}নয়, []stringবা অন্যান্য কংক্রিটের ধরণের স্লাইস তৈরি করে ।
kostix

13
-1: বার কেবল স্ট্রিং থাকলে এটিই কাজ করে, func foo(bar []string) { /* ... */ }
এক্ষেত্রে

2
কোনও টাইপ স্যুইচ ব্যবহার করুন বা স্বীকৃত উত্তরের মতো প্রতিবিম্ব ব্যবহার করুন।
ডিস্কিনার

ওপিকে রান টাইমে যে কোনও উপায়ে তার ধরণটি বের করতে হবে। স্লাইসবিহীন স্লাইস ব্যবহার করা interface{}কম্পাইলারটিকে কোনও আর্গুমেন্ট পাস করার সময় অভিযোগ না করে foo(a)। তিনি হয় অভ্যন্তরে প্রতিবিম্ব বা টাইপ স্যুইচিং ( golang.org/doc/effective_go.html#type_switch ) ব্যবহার করতে পারেন foo
ক্যাসিওহগ

2

যে interface{}কোনও ধরণের রূপান্তর করুন ।

বাক্য গঠন:

result := interface.(datatype)

উদাহরণ:

var employee interface{} = []string{"Jhon", "Arya"}
result := employee.([]string)   //result type is []string.

2
আপনি এটি সম্পর্কে নিশ্চিত? আমি এটি বৈধ মনে করি না। আপনি এটি দেখতে যাচ্ছেন: invalid type assertion: potato.([]string) (non-interface type []interface {} on left)
অ্যাড্রিয়ানো টেডাও

2

আপনার কোডটি আরও সংক্ষিপ্ত করার ক্ষেত্রে আপনি সাহায্যকারীর জন্য নতুন ধরণের তৈরি করতে পারেন

type Strings []string

func (ss Strings) ToInterfaceSlice() []interface{} {
    iface := make([]interface{}, len(ss))
    for i := range ss {
        iface[i] = ss[i]
    }
    return iface
}

তারপর

a := []strings{"a", "b", "c", "d"}
sliceIFace := Strings(a).ToInterfaceSlice()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.