একটি ইন্টারফেস-মানটির "আসল" প্রকারটি কীভাবে নির্ধারণ করবেন?


120

interface{}প্রকারগুলি ব্যবহারের জন্য আমি কোনও ভাল উত্স পাই না । উদাহরণ স্বরূপ

package main

import "fmt"

func weirdFunc(i int) interface{} {
    if i == 0 {
        return "zero"
    }
    return i
}
func main() {
    var i = 5
    var w = weirdFunc(5)

    // this example works!
    if tmp, ok := w.(int); ok {
        i += tmp
    }

    fmt.Println("i =", i)
}

আপনি কি গো এর ব্যবহার সম্পর্কে ভাল পরিচিতি জানেন interface{}?

নির্দিষ্ট প্রশ্ন:

  • আমি কীভাবে ডাব্লু "আসল" টাইপ পাই?
  • কোনও ধরণের স্ট্রিং প্রতিনিধিত্ব পেতে কি কোনও উপায় আছে?
  • কোনও মান রূপান্তর করতে কোনও ধরণের স্ট্রিং প্রতিনিধিত্ব ব্যবহার করার উপায় আছে কি?

উত্তর:


98

আপনার উদাহরণ কাজ করে। এখানে একটি সরলীকৃত সংস্করণ।

package main

import "fmt"

func weird(i int) interface{} {
    if i < 0 {
        return "negative"
    }
    return i
}

func main() {
    var i = 42
    if w, ok := weird(7).(int); ok {
        i += w
    }
    if w, ok := weird(-100).(int); ok {
        i += w
    }
    fmt.Println("i =", i)
}

Output:
i = 49

এটি টাইপ অ্যাসারেন্স ব্যবহার করে ।


তুমি একদমই সঠিক! ধন্যবাদ! প্রকারের স্ট্রিং উপস্থাপনাগুলির বিষয়ে আপনার কী অন্তর্দৃষ্টি আছে?
সিসি অল্প বয়স্ক

12
চেক আউট reflect.TypeOf
দিমিত্রি গোল্ডরিং

@ দিমিত্রিগোলডিং যা অন্তত বিষয়গুলির শিরোনামে প্রশ্নের উত্তর দেয়। এই উত্তর না। আপনাকে অনেক ধন্যবাদ.
সি

129

আপনি টাইপ সুইচগুলিও করতে পারেন:

switch v := myInterface.(type) {
case int:
    // v is an int here, so e.g. v + 1 is possible.
    fmt.Printf("Integer: %v", v)
case float64:
    // v is a float64 here, so e.g. v + 1.0 is possible.
    fmt.Printf("Float64: %v", v)
case string:
    // v is a string here, so e.g. v + " Yeah!" is possible.
    fmt.Printf("String: %v", v)
default:
    // And here I'm feeling dumb. ;)
    fmt.Printf("I don't know, ask stackoverflow.")
}

এটার জন্য ধন্যবাদ. কিন্তু এখনও সেখানে না। উদাহরণস্বরূপ, আমি কীভাবে ভার্চ ডব্লিউকে একটি অন্তর্নিহিত করতে পারি?
সিসি অল্প বয়স্ক

3
মুয়ের উদাহরণ একই কাজ করে তবে একটি বিবৃতি পরিবর্তে একটি টাইপ সুইচে in 'কেস ইন্ট' এ, 'ভি' একটি পূর্ণসংখ্যা হবে। 'ক্ষেত্রে ফ্লোট 64' এ, 'ভি' ফ্লোট 64 হবে, ইত্যাদি
জিমট

ঠিক আছে। সিনট্যাক্স ভেরি (টাইপ) ভুলে গিয়েছিল, যা চতুর এবং শীতল
সিসি অল্প বয়স্ক

51

আপনি reflect.TypeOf()কোনও কিছুর ধরণ পেতে প্রতিবিম্ব ( ) ব্যবহার করতে পারেন এবং এটি যে মান দেয় Typeতার একটি স্ট্রিং উপস্থাপনা ( Stringপদ্ধতি) থাকে যা আপনি মুদ্রণ করতে পারেন।


10
আর তুমি শুধু (ইন একটি টাইপ সুইচ লিংক ডিফল্ট ব্লক মধ্যে মুদ্রণের জন্য যেমন একটি স্ট্রিং বা একটি টাইপ পেতে চাইলে দয়া Mue এর উত্তর আপনি শুধু ব্যবহার করতে পারেন fmt'পরিবর্তে গুলি "% টি" ফরম্যাট সরাসরি ব্যবহার reflect
ডেভ সি

16

এখানে স্যুইচ এবং প্রতিবিম্ব উভয়ই ব্যবহার করে জেনেরিক মানচিত্রটি ডিকোড করার একটি উদাহরণ রয়েছে, সুতরাং আপনি যদি এই ধরণের সাথে মেলে না তবে এটি বের করার জন্য প্রতিবিম্বটি ব্যবহার করুন এবং তারপরে টাইপটি যুক্ত করুন।

var data map[string]interface {}

...

for k, v := range data {
    fmt.Printf("pair:%s\t%s\n", k, v)   

    switch t := v.(type) {
    case int:
        fmt.Printf("Integer: %v\n", t)
    case float64:
        fmt.Printf("Float64: %v\n", t)
    case string:
        fmt.Printf("String: %v\n", t)
    case bool:
        fmt.Printf("Bool: %v\n", t)
    case []interface {}:
        for i,n := range t {
            fmt.Printf("Item: %v= %v\n", i, n)
        }
    default:
        var r = reflect.TypeOf(t)
        fmt.Printf("Other:%v\n", r)             
    }
}

6

টাইপ সুইচগুলি প্রতিবিম্ব স্টাফগুলির সাথেও ব্যবহার করা যেতে পারে:

var str = "hello!"
var obj = reflect.ValueOf(&str)

switch obj.Elem().Interface().(type) {
case string:
    log.Println("obj contains a pointer to a string")
default:
    log.Println("obj contains something else")
}

2

আমি একটি স্থানীয় ধরণের রিসিভারের প্রতিচ্ছবি প্রকারের একটি যুক্তি পাস করার উপর ভিত্তি করে একটি বুলিয়ান ফেরত দেওয়ার একটি উপায় উপস্থাপন করতে যাচ্ছি (কারণ আমি এর মতো কিছুই পাইনি)।

প্রথমে, আমরা আমাদের বেনামে প্রকারের প্রতিবিম্বের প্রকার ঘোষণা করি V মূল্য:

type AnonymousType reflect.Value

তারপরে আমরা আমাদের স্থানীয় টাইপ অ্যানোনিমাস টাইপের জন্য এমন একটি বিল্ডার যুক্ত করব যা কোনও সম্ভাব্য ধরণের (ইন্টারফেস হিসাবে) নিতে পারে:

func ToAnonymousType(obj interface{}) AnonymousType {
    return AnonymousType(reflect.ValueOf(obj))
}

তারপরে আমরা আমাদের বেনামে টাইপ স্ট্রাক্টের জন্য একটি ফাংশন যুক্ত করব যা প্রতিবিম্বের বিরুদ্ধে দৃ as়ভাবে দাবি করে ind

func (a AnonymousType) IsA(typeToAssert reflect.Kind) bool {
    return typeToAssert == reflect.Value(a).Kind()
}

এটি আমাদের নিম্নলিখিতগুলিতে কল করতে দেয়:

var f float64 = 3.4

anon := ToAnonymousType(f)

if anon.IsA(reflect.String) {
    fmt.Println("Its A String!")
} else if anon.IsA(reflect.Float32) {
    fmt.Println("Its A Float32!")
} else if anon.IsA(reflect.Float64) {
    fmt.Println("Its A Float64!")
} else {
    fmt.Println("Failed")
}

এখানে দীর্ঘতর, কার্যক্ষম সংস্করণ দেখতে পাবেন: https://play.golang.org/p/EIAp0z62B7


1

কোনও ধরণের স্ট্রিং উপস্থাপনা পাওয়ার জন্য একাধিক উপায় রয়েছে। সুইচগুলি ব্যবহারকারীর ধরণের সাথেও ব্যবহার করা যেতে পারে:

var user interface{}
user = User{name: "Eugene"}

// .(type) can only be used inside a switch
switch v := user.(type) {
case int:
    // Built-in types are possible (int, float64, string, etc.)
    fmt.Printf("Integer: %v", v)
case User:
    // User defined types work as well  
    fmt.Printf("It's a user: %s\n", user.(User).name)
}

// You can use reflection to get *reflect.rtype
userType := reflect.TypeOf(user)
fmt.Printf("%+v\n", userType)

// You can also use %T to get a string value
fmt.Printf("%T", user)

// You can even get it into a string
userTypeAsString := fmt.Sprintf("%T", user)

if userTypeAsString == "main.User" {
    fmt.Printf("\nIt's definitely a user")
}

খেলার মাঠের লিঙ্ক: https://play.golang.org/p/VDeNDUd9uK6

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