ইন্টারফেস ওভারের পরিসীমা {} যা একটি স্লাইস সঞ্চয় করে


99

আপনার এমন কোনও ফাংশন রয়েছে যা গ্রহণ করবে সেই দৃশ্যে t interface{}। যদি এটি নির্ধারিত হয় যে এটি tএকটি স্লাইস, তবে আমি কীভাবে rangeসেই ফালিটি কাটিয়ে দেব ?

func main() {
    data := []string{"one","two","three"}
    test(data)
    moredata := []int{1,2,3}
    test(data)
}

func test(t interface{}) {
    switch reflect.TypeOf(t).Kind() {
    case reflect.Slice:
        // how do I iterate here?
        for _,value := range t {
            fmt.Println(value)
        }
    }
}

খেলার মাঠের উদাহরণটিতে যান: http://play.golang.org/p/DNldAlNShB


পরিবর্তে ফাংশনটি কেন একটি [] ইন্টারফেস take take নেবে না? আপনি কি একাধিক জটিল ধরণের পরিচালনা করার চেষ্টা করছেন?
জেরেমি ওয়াল

4
হ্যাঁ, এটি একটি টেম্প্লেটিং সিস্টেমের জন্য তাই ইন্টারফেস {a একটি মানচিত্র, কাঠামো, স্লাইস বা অ্যারে হতে পারে। আসল কোডে আরও অনেক কেস স্টেটমেন্ট রয়েছে তবে সমস্যাটি আরও সংকীর্ণ করতে আমি এগুলি পোস্ট থেকে সরিয়েছি।
নিউক্লিওন

4
জেরেমি, একটি [] স্ট্রিং [] ইন্টারফেস {a এর উপপ্রকার নয়, সুতরাং আপনি একটি [] স্ট্রিং বা [] ইনট, ইত্যাদির সাথে একটি ফানক ([]] ইন্টারফেস {}) ফাংশন বলতে পারবেন না এটি ভাল লাগবে Go তে একটি বৈশিষ্ট্য রয়েছে যার অর্থ "কোনও কিছুর স্লাইস" রয়েছে, যেখানে আপনি উপাদানগুলির পরে ইন্টারফেস {} হিসাবে পুনরাবৃত্তি করতে পারেন, তবে দুর্ভাগ্যক্রমে এর জন্য আপনাকে প্রতিবিম্বের প্রয়োজন হবে।
বার্জার এবার্ট

@ জেরেমিওয়াল আপনি স্লাইস হিসাবে কাজ করতে [] ইন্টারফেস {use ব্যবহার করতে পারবেন না। আপনি এখানে উল্লেখ করতে পারেন ।
অগ্নি

উত্তর:


138

ভাল আমি ব্যবহার করেছি reflect.ValueOfএবং তারপরে যদি এটি একটি স্লাইস হয় তবে আপনি কল করতে পারেন Len()এবং একটি সূচীতে স্লাইস এবং উপাদানটির Index()মান পেতে len। আমি মনে করি না এটি করতে আপনি ব্যাপ্তিটি পরিচালনা করতে সক্ষম হবেন।

package main

import "fmt"
import "reflect"

func main() {
    data := []string{"one","two","three"}
    test(data)
    moredata := []int{1,2,3}
    test(moredata)
} 

func test(t interface{}) {
    switch reflect.TypeOf(t).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(t)

        for i := 0; i < s.Len(); i++ {
            fmt.Println(s.Index(i))
        }
    }
}

খেলার মাঠের উদাহরণটিতে যান: http://play.golang.org/p/gQhCTiwPAq


26
দুর্দান্ত কাজ করে, আপনাকে ধন্যবাদ। যুক্ত করার একমাত্র জিনিসটি s.Index(i)হ'ল reflect.Valueআমার ক্ষেত্রে s.Index(i).Interface()সত্যিকারের মানটি উল্লেখ করার দরকার রয়েছে returns
নিউক্লিওন

4
আপনি যদি একটি টুকরো টুকরো করার পয়েন্টার পেয়ে থাকেন তবে আপনি কী করবেন interface{}? যেমন moredata := &[]int{1,2,3}
রায়ান ওয়ালস

4
আমার প্রশ্নের উত্তরের: আপনার যদি স্লাইসের পরিবর্তে কোনও স্লাইসের পয়েন্টার থাকে Elem()তবে অন্তর্নিহিত মানটি পেতে আপনাকে ব্যবহার করতে হবে। যেমন reflect.TypeOf(reflect.ValueOf(t).Elem().Interface()).Kind()
রায়ান ওয়ালস

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

অনেক ধন্যবাদ, সেই কৌশলটি আমাকে অনেক সময় বাঁচিয়েছিল (এবং মাথাব্যথা!)
নিকোলাস গার্নিয়ার

26

কোন ধরণের প্রত্যাশা করা উচিত তা যদি আপনার জানা থাকে তবে আপনার প্রতিবিম্ব ব্যবহার করার দরকার নেই। আপনি এই জাতীয় টাইপ সুইচ ব্যবহার করতে পারেন :

package main

import "fmt"

func main() {
    loop([]string{"one", "two", "three"})
    loop([]int{1, 2, 3})
}

func loop(t interface{}) {
    switch t := t.(type) {
    case []string:
        for _, value := range t {
            fmt.Println(value)
        }
    case []int:
        for _, value := range t {
            fmt.Println(value)
        }
    }
}

খেলার মাঠে কোড পরীক্ষা করে দেখুন


এটি কোনও অ্যারেতে কাজ করবে না, কেবল এক টুকরো দিয়ে
ব্যবহারকারী 1028741

@ user1028741 না, কোড অ্যারে সহ প্রতিটি ধরণের জন্য কাজ করে + আপনি সর্বদা অ্যারে থেকে একটি স্লাইস নিতে পারেন array[:]
Inanc Gumus

তবে অ্যারের ধরণটি এর আসল ক্ষমতা সহ হবে। [3] ইনট [2] ইনট বা [] ইনট হিসাবে একই ধরণের নয়। সুতরাং, 't' টাইপটি আসলে অ্যারে হলে প্রাসঙ্গিক কেস প্রযোজ্য হবে না।
ব্যবহারকারী 1028741

4
আমি যা বলতে চাইছি তা হল আপনার উদাহরণ অ্যারেগুলিতে কাজ করবে না। আমি এখানে এটি পরিবর্তন করেছি: play.golang.org/p/DAsg_0aXz-r
ব্যবহারকারী 1028741

আপনি যদি প্রথমে আপনার প্যারামিটারের ধরন জানেন না তবে আপনি এটিকে সহজেই কাজ করতে পারবেন না। আপনার কৌতুকটি (অ্যারে [:]) ব্যবহার করার জন্য, আপনাকে এটি একটি অ্যারে কিনা তা স্থির করতে প্রতিফলন ব্যবহার করতে হবে, তারপরে অ্যারেতে কাস্ট করতে হবে - তারপরে এটির একটি টুকরো তৈরি করতে হবে। সে কারণেই আমি বলেছিলাম এটি কোনও অ্যারে নয়, একটি স্লাইসে কাজ করে। পরিষ্কার পরিশ্রমে আপনি অ্যারে থেকে একটি স্লাইস উত্পাদন করতে পারেন ...
ব্যবহারকারী 1028741

4

ইন্টারফেস {} যেভাবে আচরণ করে তার মধ্যে একটি ব্যতিক্রম রয়েছে, @ জেরেমি ওয়াল ইতিমধ্যে পয়েন্টার দিয়েছে। যদি পাস করা ডেটা প্রাথমিকভাবে [] ইন্টারফেস} as হিসাবে সংজ্ঞায়িত হয়।

package main

import (
    "fmt"
)

type interfaceSliceType []interface{}

var interfaceAsSlice interfaceSliceType

func main() {
    loop(append(interfaceAsSlice, 1, 2, 3))
    loop(append(interfaceAsSlice, "1", "2", "3"))
    // or
    loop([]interface{}{[]string{"1"}, []string{"2"}, []string{"3"}})
    fmt.Println("------------------")


    // and of course one such slice can hold any type
    loop(interfaceSliceType{"string", 999, map[int]string{3: "three"}})
}

func loop(slice []interface{}) {
    for _, elem := range slice {
        switch elemTyped := elem.(type) {
        case int:
            fmt.Println("int:", elemTyped)
        case string:
            fmt.Println("string:", elemTyped)
        case []string:
            fmt.Println("[]string:", elemTyped)
        case interface{}:
            fmt.Println("map:", elemTyped)
        }
    }
}

আউটপুট:

int: 1
int: 2
int: 3
string: 1
string: 2
string: 3
[]string: [1]
[]string: [2]
[]string: [3]
------------------
string: string
int: 999
map: map[3:three]

চেষ্টা কর

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.