2011-08-09 11 views
32

मैं कुछ सी कार्यों इसजाओ भाषा में कार्यावधि में चर प्रकार की जांच कैसे

CURLcode curl_wrapper_easy_setopt_long(CURL* curl, CURLoption option, long param); 
CURLcode curl_wrapper_easy_setopt_str(CURL* curl, CURLoption option, char* param); 

की तरह घोषित मैं इस

func (e *Easy)SetOption(option Option, param interface{}) 

तो मैं की जरूरत है की तरह एक जाओ समारोह के रूप में उन का पर्दाफाश करना चाहते हैं परम रनटाइम पर टाइप करने में सक्षम होने के लिए। मैं यह कैसे कर सकता हूं और यह अच्छा विचार है (यदि इस मामले में अच्छा अभ्यास नहीं है)?

उत्तर

11

देखें प्रकार यहाँ दावे:

http://golang.org/ref/spec#Type_assertions

मैं एक समझदार प्रकार (स्ट्रिंग, uint64) आदि ही जोर है और यह संभव के रूप में ढीला रखें, देशी प्रकार पिछले एक रूपांतरण प्रदर्शन चाहते हैं।

+9

उत्तर पूर्ण होना चाहिए, सिर्फ लिंक ही नहीं। कृपया इस जवाब को दूर करो। – Flimzy

+2

नोट: यह कंक्रीट प्रकारों, केवल इंटरफ़ेस प्रकारों के लिए काम नहीं करता है। – darethas

-1

क्या

func (e *Easy)SetStringOption(option Option, param string) 
func (e *Easy)SetLongOption(option Option, param long) 

और इतने पर के साथ गलत क्या है?

+0

क्योंकि सी libCURL लाइब्रेरी में curl_easy_setopt (curl * curl, curloption विकल्प, ...) सेटिंग विकल्प के लिए केवल एक फ़ंक्शन है। लेकिन कागो varargs का समर्थन नहीं करता है इसलिए मैंने प्रत्येक प्रकार के पैरामीटर के लिए सी में रैपर फ़ंक्शन बनाया है। मुझे लगता है कि गो इंटरफ़ेस जितना संभव हो सके सी के करीब होना चाहिए। यदि उपयोगकर्ता libCURL (सी या अन्य भाषा से) जानता है, तो मैं उसे घर पर सही महसूस करना चाहता हूं;) –

+0

खेल के लिए देर हो चुकी है, लेकिन मैं उस दृष्टिकोण के खिलाफ बहस करता हूं! आप पुस्तकालय को * जाओ * उपयोगकर्ता के घर पर महसूस करना चाहते हैं। (सबसे अच्छा उदाहरण जहां curl जैसे निचले स्तर के पुस्तकालयों के प्रत्यक्ष बंदरगाह लोगों को भ्रमित करते हैं ... PHP) – Nevir

47

ऐसा लगता है स्विच की विशेष रूप (यह प्रकार स्विच कहा जाता है) यह करने के लिए समर्पित है कि जाओ:

func (e *Easy)SetOption(option Option, param interface{}) { 

    switch v := param.(type) { 
    default: 
     fmt.Printf("unexpected type %T", v) 
    case uint64: 
     e.code = Code(C.curl_wrapper_easy_setopt_long(e.curl, C.CURLoption(option), C.long(v))) 
    case string: 
     e.code = Code(C.curl_wrapper_easy_setopt_str(e.curl, C.CURLoption(option), C.CString(v))) 
    } 
} 
+0

क्या यह वाक्यविन्यास केवल 'स्विच' में उपयोग किया जा सकता है? उदाहरण के लिए यदि मुझे केवल 1 मामले की परवाह है तो शायद एक स्विच ओवरकिल हो सकता है? –

+0

@NathanH हां, इस तरह से केवल स्विच के लिए काम करता है (गो 1.10 के साथ परीक्षण किया गया) – MewX

36

@Darius द्वारा जवाब सबसे मुहावरेदार (और शायद अधिक performant) विधि है। एक सीमा यह है कि जिस प्रकार आप जांच रहे हैं वह interface{} प्रकार होना चाहिए। यदि आप एक ठोस प्रकार का उपयोग करते हैं तो यह असफल हो जाएगा।

कंक्रीट प्रकारों सहित रन-टाइम पर किसी प्रकार के प्रकार को निर्धारित करने का एक वैकल्पिक तरीका गो reflect पैकेज का उपयोग करना है। http://golang.org/pkg/reflect/#Kind

फिर आप एक स्विच ब्लॉक के बाहर प्रकार के लिए जांच कर सकते हैं, तो जैसे:

import (
    "fmt" 
    "reflect" 
) 

// .... 

x := 42 
y := float32(43.3) 
z := "hello" 

xt := reflect.TypeOf(x).Kind() 
yt := reflect.TypeOf(y).Kind() 
zt := reflect.TypeOf(z).Kind() 

fmt.Printf("%T: %s\n", xt, xt) 
fmt.Printf("%T: %s\n", yt, yt) 
fmt.Printf("%T: %s\n", zt, zt) 

if xt == reflect.Int { 
    println(">> x is int") 
} 
if yt == reflect.Float32 { 
    println(">> y is float32") 
} 
if zt == reflect.String { 
    println(">> z is string") 
} 

कौन सा बहिष्कार प्रिंट:

चेनिंग TypeOf(x).Kind() एक साथ आप एक reflect.Kind मूल्य जो एक uint प्रकार है प्राप्त कर सकते हैं
reflect.Kind: int 
reflect.Kind: float32 
reflect.Kind: string 
>> x is int 
>> y is float32 
>> z is string 

फिर से, यह संभवतः ऐसा करने का पसंदीदा तरीका नहीं है, लेकिन वैकल्पिक विकल्पों को जानना अच्छा है।

+0

आपको '.ind()' क्यों चाहिए? यह इसके बिना काम करता है। – karantan

+0

@ karantan quux00 के कोड के अनुसार .किंड() की आवश्यकता है। अन्यथा आप संकलन समय त्रुटि प्राप्त करेंगे। https://golang.org/pkg/reflect/#Kind एक प्रकार विशिष्ट प्रकार के प्रकार का प्रतिनिधित्व करता है जो एक प्रकार का प्रतिनिधित्व करता है https://golang.org/pkg/reflect/#TypeOf वापसी प्रकार इंटरफ़ेस {} – Mujibur

0

quux00 का उत्तर केवल मूल प्रकारों की तुलना करने के बारे में बताता है।

यदि आपको परिभाषित प्रकारों की तुलना करने की आवश्यकता है, तो आपको reflect.TypeOf(xxx) का उपयोग नहीं करना चाहिए। इसके बजाय, reflect.TypeOf(xxx).Kind() का उपयोग करें।

ये दो प्रकार की श्रेणियां हैं:

  • प्रत्यक्ष प्रकार (प्रकार आपको सीधे परिभाषित)
  • बुनियादी प्रकार (पूर्णांक, float64, struct, ...)

यहाँ एक पूर्ण उदाहरण है:

type MyFloat float64 
type Vertex struct { 
    X, Y float64 
} 

type EmptyInterface interface {} 

type Abser interface { 
    Abs() float64 
} 

func (v Vertex) Abs() float64 { 
    return math.Sqrt(v.X*v.X + v.Y*v.Y) 
} 

func (f MyFloat) Abs() float64 { 
    return math.Abs(float64(f)) 
} 

var ia, ib Abser 
ia = Vertex{1, 2} 
ib = MyFloat(1) 
fmt.Println(reflect.TypeOf(ia)) 
fmt.Println(reflect.TypeOf(ia).Kind()) 
fmt.Println(reflect.TypeOf(ib)) 
fmt.Println(reflect.TypeOf(ib).Kind()) 

if reflect.TypeOf(ia) != reflect.TypeOf(ib) { 
    fmt.Println("Not equal typeOf") 
} 
if reflect.TypeOf(ia).Kind() != reflect.TypeOf(ib).Kind() { 
    fmt.Println("Not equal kind") 
} 

ib = Vertex{3, 4} 
if reflect.TypeOf(ia) == reflect.TypeOf(ib) { 
    fmt.Println("Equal typeOf") 
} 
if reflect.TypeOf(ia).Kind() == reflect.TypeOf(ib).Kind() { 
    fmt.Println("Equal kind") 
} 

उत्पादन होगा:

main.Vertex 
struct 
main.MyFloat 
float64 
Not equal typeOf 
Not equal kind 
Equal typeOf 
Equal kind 

आप देख सकते हैं, reflect.TypeOf(xxx) प्रत्यक्ष प्रकार जो आप उपयोग करना चाहते हो सकता है देता है, जबकि reflect.TypeOf(xxx).Kind() मूल प्रकार देता है।


यहां निष्कर्ष निकाला गया है। यदि आपको मूल प्रकारों की तुलना करने की आवश्यकता है, तो reflect.TypeOf(xxx).Kind() का उपयोग करें; और यदि आपको स्वयं परिभाषित प्रकारों की तुलना करने की आवश्यकता है, तो reflect.TypeOf(xxx) का उपयोग करें।

if reflect.TypeOf(ia) == reflect.TypeOf(Vertex{}) { 
    fmt.Println("self-defined") 
} else if reflect.TypeOf(ia).Kind() == reflect.Float64 { 
    fmt.Println("basic types") 
} 
संबंधित मुद्दे