2012-03-10 20 views
22

गो में, समानता के परीक्षण के लिए दो गैर-शून्य फ़ंक्शन पॉइंटर्स की तुलना करने का कोई तरीका है? समानता का मेरा मानक सूचक समानता है। यदि नहीं, तो क्या कोई विशेष कारण है कि पॉइंटर समानता की अनुमति नहीं है?नवीनतम गो साप्ताहिक में पॉइंटर समानता के लिए मैं दो कार्यों की तुलना कैसे करूं?

फिलहाल, अगर मैं सीधी-सपाट रास्ते में यह करने के लिए प्रयास करते हैं:

package main 

import "fmt" 

func SomeFun() { 
} 

func main() { 
    fmt.Println(SomeFun == SomeFun) 
} 

मैं

./func-pointers.go:12: invalid operation: SomeFun == SomeFun (func can only be compared to nil) 

यह मेरी समझ है कि इस व्यवहार हाल ही में शुरू किया गया था।


मुझे प्रतिबिंबित पैकेज का उपयोग करके एक जवाब मिला है; हालांकि एटम नीचे बताता है कि यह वास्तव में अपरिभाषित व्यवहार पैदा करता है। अधिक जानकारी और संभावित वैकल्पिक समाधान के लिए एटम की पोस्ट देखें।

package main 

import "fmt" 
import "reflect" 

func SomeFun() { } 

func AnotherFun() { } 

func main() { 
    sf1 := reflect.ValueOf(SomeFun) 
    sf2 := reflect.ValueOf(SomeFun) 
    fmt.Println(sf1.Pointer() == sf2.Pointer()) 

    af1 := reflect.ValueOf(AnotherFun) 
    fmt.Println(sf1.Pointer() == af1.Pointer()) 
} 

आउटपुट:

true 
false 

उत्तर

35

ध्यान दें कि समानता और पहचान के बीच कोई अंतर है। Go1 में ऑपरेटर == और != समानता के लिए मानों की तुलना कर रहे हैं (चैनल की तुलना करते समय छोड़कर), पहचान के लिए नहीं। चूंकि ये ऑपरेटर समानता और पहचान को मिश्रण करने के लिए को आजमा रहे हैं, तो Go1 इस संबंध में प्री-गो 1 से अधिक संगत है।

फ़ंक्शन समानता फ़ंक्शन पहचान से अलग है। समारोह प्रकार पर == और != की अनुमति नहीं दे के लिए


एक कारण यह प्रदर्शन है।

f := func(){fmt.Println("foo")} 

अनुमति नहीं दी जाएगी कार्यों की तुलना सक्षम संकलक एक नया बंद बनाने के लिए बंद करने के लिए एक एकल कार्यान्वयन उत्पन्न करने के लिए, बजाय चलाने के समय की आवश्यकता होती है: उदाहरण के लिए, निम्नलिखित बंद अपने पर्यावरण से किसी भी वैरिएबल का उपयोग नहीं कर रहा है (चलने के समय पर)। तो, प्रदर्शन दृष्टिकोण से फ़ंक्शन तुलना को अस्वीकार करने का निर्णय एक अच्छा निर्णय था।


संबंध में reflect पैकेज का उपयोग समारोह पहचान, जैसे

func SomeFun() {} 
func AnotherFun() {} 

func main() { 
    sf1 := reflect.ValueOf(SomeFun) 
    sf2 := reflect.ValueOf(SomeFun) 
    fmt.Println(sf1.Pointer() == sf2.Pointer()) // Prints true 

    af1 := reflect.ValueOf(AnotherFun) 
    fmt.Println(sf1.Pointer() == af1.Pointer()) // Prints false 
} 

एक कोड निर्धारित करने के लिए करने के लिए अपरिभाषित व्यवहार पर निर्भर करता है। इस कार्यक्रम की कोई गारंटी नहीं है कि कार्यक्रम क्या प्रिंट करेगा। संकलक यह तय कर सकता है कि यह SomeFun और AnotherFun को एक ही कार्यान्वयन में विलय करेगा, इस मामले में दूसरा प्रिंट स्टेटमेंट true प्रिंट करेगा। वास्तव में, बिल्कुल कोई गारंटी नहीं है कि पहला प्रिंट स्टेटमेंट true प्रिंट करेगा (यह हो सकता है कि, कुछ अन्य गो 1 कंपाइलर और रन-टाइम के तहत, false प्रिंट करें)।


अपने मूल प्रश्न के लिए एक सही जवाब है:

package main 

import "fmt" 

func F1() {} 
func F2() {} 

var F1_ID = F1 // Create a *unique* variable for F1 
var F2_ID = F2 // Create a *unique* variable for F2 

func main() { 
    f1 := &F1_ID // Take the address of F1_ID 
    f2 := &F2_ID // Take the address of F2_ID 

    // Compare pointers 
    fmt.Println(f1 == f1) // Prints true 
    fmt.Println(f1 == f2) // Prints false 
} 
+1

उत्कृष्ट प्रतिक्रिया। धन्यवाद! आपको निश्चित रूप से "क्यों" का जवाब देने के लिए क्रेडिट मिलता है, लेकिन मैं अपने मूल प्रश्न के उत्तर के बारे में उलझन में हूं। ऐसा प्रतीत होता है कि यह F1 और F2 कार्यों की पहचान के बजाय चर F1_ID और F2_ID की पहचान का परीक्षण कर रहा है। उदाहरण के लिए, यदि मेरे पास 'var F1_ID2 = F1' था, तो यदि हम फ़ंक्शन पहचान का परीक्षण कर रहे थे तो F1_ID == और F1_ID2 सत्य वापस आ जाएंगे; लेकिन यह झूठी वापसी करता है। – BurntSushi5

+0

इसके अलावा, प्रतिबिंबित करने के माध्यम से मेरे दृष्टिकोण की आपकी आलोचना मुझे चिंतित करती है। क्या आप सुझाव नहीं दे रहे हैं कि परीक्षण कार्य पहचान पहचान में गारंटी देना असंभव है? – BurntSushi5

+1

टिप्पणी 1: अंतिम कोड स्निपेट में धारणा यह है कि एक विशेष फ़ंक्शन में एक आईडी होती है। –

1

weekly.2011-11-18

मानचित्र और समारोह मूल्य की तुलना अब प्रति जाओ 1 योजना के रूप में (शून्य साथ तुलना के लिए छोड़कर) अनुमति नहीं है। फ़ंक्शन समानता कुछ संदर्भों में समस्याग्रस्त और मानचित्र समानता तुलना पॉइंटर्स, मानचित्र की सामग्री नहीं थी। (जब दो बंदी बराबर हैं?)

Equality

समारोह समानता बंद की उपस्थिति में समस्याग्रस्त था

+3

मुझे नहीं लगता कि यह वास्तव में मेरे सवाल का जवाब है। मुझे पता है कि जिस तरह से मैं उपयोग कर रहा हूं उसमें फ़ंक्शन वैल्यू तुलना की अनुमति नहीं है; मैं क्या जानना चाहता हूं कि क्या कोई कामकाज है। मैं यह भी जानना चाहूंगा कि क्यों * सूचक * समानता समस्याग्रस्त है। – BurntSushi5

+1

@ BurntSushi5 यह एक अच्छा सवाल है। निश्चित रूप से ऐसी भाषाएं होती हैं जिनमें बंद होते हैं जहां आप फ़ंक्शन पॉइंटर्स की तुलना कर सकते हैं। एक ही फ़ंक्शन के क्लोजर * जो अलग-अलग चर पर बंद होते हैं, उन भाषाओं में बराबर परीक्षण नहीं करते हैं। ऐसा लगता है कि यह सिर्फ एक प्रतिनिधित्व मुद्दा है। गो में जाने की अनुमति क्यों नहीं है इसके मूलभूत कारण हैं। यह ** एक समझदार, विश्वसनीय, और लगातार तरीके से लागू किया जा सकता है; उन्होंने बस ऐसा नहीं करना चुना है। – tchrist

+0

@peterSO आपके संपादन के जवाब में: यह वास्तव में उत्तर नहीं देता है कि फ़ंक्शन पॉइंटर समानता का उपयोग क्यों नहीं किया जा सकता है। यदि दो फ़ंक्शन पॉइंटर्स एक ही स्मृति स्थान पर इंगित करते हैं, तो वे बराबर होना चाहिए। यह कार्य समानता के सामान्य रूप के रूप में काफी उपयोगी नहीं होगा, लेकिन यह बेकार नहीं होगा। – BurntSushi5

3

वैकल्पिक हल situtation पर निर्भर करता है। मुझे कुछ स्थानों को बदलना पड़ा जहां मैं कार्यों की तुलना कर रहा था। एक बार मामले में मैंने अभी कुछ अलग किया है इसलिए मुझे उनकी तुलना करने की आवश्यकता नहीं होगी। एक अन्य मामले में मैं इन structs का एक टुकड़ा रखने के लिए और टुकड़ा स्कैन करने के लिए

type nameFunc struct { 
    name string 
    fval func() 
} 

तुलनीय तार के साथ काम करता है संबद्ध करने के लिए एक struct, की तरह कुछ, मैं केवल था कार्यों की एक जोड़ी मैं तो तुलना करने के लिए की जरूरत है यह सबसे सरल था इस्तेमाल किया आवश्यकतानुसार, नाम फ़ील्ड की तुलना और fval प्रेषण। यदि आपके पास बहुत सारे हैं तो आप इसके बजाय मानचित्र का उपयोग कर सकते हैं। यदि आपके कार्यों में अलग-अलग हस्ताक्षर हैं तो आप इंटरफेस का उपयोग कर सकते हैं, और इसी तरह।

+0

आह अच्छा। मैंने अपने दृष्टिकोण को बदलकर इसके आसपास भी काम किया है। फ़ंक्शन के स्ट्रिंग प्रस्तुति को रखने के बारे में टिप के लिए धन्यवाद। यह मैं जो कर रहा हूं उसके लिए अच्छा काम नहीं करेगा (लाइब्रेरी में मनमाने ढंग से कॉलबैक फ़ंक्शन की अनुमति देता है), लेकिन यह लाइन के नीचे उपयोगी हो सकता है। – BurntSushi5

+0

प्रतिबिंबित पैकेज में जो मैं ढूंढ रहा था वह है। मैंने जवाब के साथ अपना ओपी अपडेट किया है। – BurntSushi5

संबंधित मुद्दे