2012-06-21 11 views
19

मैं समारोहसमारोह के रूप में संकेत पर golang संकेत दिए गए मानकों

func addCatsToMap(m map[string][]CatHouse, meowId int, treats Set, dog *Dog) { 

//if (complicated thing) add Cat to m 

} 

है यह सच है कि मीटर, दावतों और कुत्ते से पारित कर दिया-दर-संदर्भ कर रहे हैं, और meowId यह मूल्य की नकल की है है।

चूंकि एम मानचित्र है, इसका पास-दर-संदर्भ है।

कुत्ता एक संरचना है। इसलिए, मुझे डेटा कॉपी करने से बचने के लिए पॉइंटर पास करना चाहिए।

type Set interface { 
    Add(value string) 
    Contains(value string) (bool) 
    Length() (int) 
    RemoveDuplicates() 
} 

पास-दर-मूल्य निर्धारित है: के रूप में यहां बताए गए

सेट, एक अंतरफलक है?

उत्तर

37

एक इंटरफ़ेस प्रकार बस विधियों का एक सेट है। ध्यान दें कि एक इंटरफ़ेस परिभाषा के सदस्य निर्दिष्ट नहीं करते हैं कि रिसीवर प्रकार एक सूचक है या नहीं। ऐसा इसलिए है क्योंकि किसी मान प्रकार का विधि सेट इसके संबंधित सूचक प्रकार के विधि सेट का सबसेट है। यह एक मुट्ठी भर है।क्या मेरा मतलब है, है अगर आपके पास निम्न:

type Whatever struct { 
    Name string 
} 

और आपको निम्न दो विधियों को परिभाषित:,

func (w *Whatever) Foo() { 
    ... 
} 

func (w Whatever) Bar() { 
    ... 
} 

फिर प्रकार Whatever एकमात्र तरीका Bar() है, जबकि प्रकार *Whatever तरीकों है Foo() और Bar()। इसका मतलब है कि यदि आप निम्नलिखित इंटरफेस है:

type Grits interface { 
    Foo() 
    Bar() 
} 

फिर *WhateverGrits लागू करता है लेकिन Whatever नहीं हुआ, क्योंकि Whatever विधि Foo() का अभाव है। जब आप किसी फ़ंक्शन में इंटरफ़ेस प्रकार के रूप में इनपुट को परिभाषित करते हैं, तो आपको पता नहीं है कि यह एक सूचक या मान प्रकार है या नहीं। ,,

package main 

import "fmt" 

type Fruit struct { 
    Name string 
} 

func (f Fruit) Rename(name string) { 
    f.Name = name 
} 

type Candy struct { 
    Name string 
} 

func (c *Candy) Rename(name string) { 
    c.Name = name 
} 

type Renamable interface { 
    Rename(string) 
} 

func Rename(v Renamable, name string) { 
    v.Rename(name) 
    // at this point, we don't know if v is a pointer type or not. 
} 

func main() { 
    c := Candy{Name: "Snickers"} 
    f := Fruit{Name: "Apple"} 
    fmt.Println(f) 
    fmt.Println(c) 
    Rename(f, "Zemo Fruit") 
    Rename(&c, "Zemo Bar") 
    fmt.Println(f) 
    fmt.Println(c) 
} 

आप Raname(&f, "Jorelli Fruit") नहीं बल्कि Rename(c, "Jorelli Bar") कह सकते हैं क्योंकि दोनों Fruit और *FruitRenamable लागू *CandyRenable लागू करता है और Candy को नहीं हुई:

निम्न उदाहरण एक समारोह है कि दोनों तरीकों से एक अंतरफलक प्रकार लेता है दिखाता है ।

http://play.golang.org/p/Fb-L8Bvuwj

6

संदर्भ द्वारा पास एक भाषा बात है, गो में कुछ भी नहीं है "संदर्भ द्वारा पास करें"। संदर्भ द्वारा पास का मतलब है कि असाइनमेंट ऑपरेटर अकेले उपयोग करते समय मूल मान बदल सकता है। हालांकि, ऐसे संदर्भ प्रकार हैं जैसे मानचित्र और पॉइंटर्स जो कहीं भी इंगित करते हैं। उन पर असाइनमेंट ऑपरेटर का उपयोग तब तक मूल को संशोधित नहीं करेगा जब तक कि आप मैप इंडेक्स और * ऑपरेटर जैसे अन्य ऑपरेटरों का उपयोग न करें।

आप सही हैं कि आपका मानचित्र m एक संदर्भ प्रकार है और इसलिए एक सूचक की तरह है। मानचित्र को बदलने के अलावा मानचित्र में कोई भी परिवर्तन मूल को संशोधित करेगा।

m["whatever"] = 2   // Modifies the original map 
m = anothermap    // Does not modify the original map 

यदि "संदर्भ द्वारा पारित" सत्य था, तो दूसरा उदाहरण मूल मानचित्र को संशोधित करेगा।

एक पॉइंटर पास करना, जैसा कि आप dog के साथ करते हैं, आपको मूल को संशोधित करने की अनुमति देता है। यदि आप किसी भी पॉइंटर विधियों को कॉल करते हैं या * ऑपरेटर का उपयोग करते हैं, तो मूल बदल जाएगा। आपके उदाहरण में, एक सूचक की आवश्यकता नहीं हो सकती है। यदि Dog छोटा है, तो बस एक प्रति पास करना आसान हो सकता है। यह निर्धारित करने के लिए प्रोग्रामर पर निर्भर करता है कि यह सूचक का उपयोग करने का एक अच्छा समय कब होता है।

Set संदर्भ द्वारा पारित नहीं किया गया है। इंटरफेस संदर्भ नहीं हैं। हालांकि यह सच है कि आंतरिक रूप से 6 जी कंपाइलर में इंटरफ़ेस पॉइंटर्स का उपयोग करता है, इंटरफ़ेस स्वयं एक जैसा कार्य नहीं करता है। एक इंटरफ़ेस पास करना, इसमें ऑब्जेक्ट के आकार का कोई फर्क नहीं पड़ता, 6 जी कंपाइलर का उपयोग करके पॉइंटर पास करने के रूप में सस्ता है। हालांकि, इंटरफ़ेस के मूल मान को संशोधित करने का कोई तरीका नहीं है जैसा कि आप पॉइंटर्स और मानचित्रों के साथ कर सकते हैं।

हालांकि आप मूल इंटरफ़ेस को संशोधित नहीं कर सकते हैं, इंटरफ़ेस में पॉइंटर प्रकार हो सकता है। उस स्थिति में यह कुत्ते सूचक की तरह कार्य करेगा जहां कुछ तरीकों की कॉलिंग मूल को संशोधित कर सकती है। आपके विशेष Set इंटरफ़ेस के लिए, मुझे लगता है कि इसमें विधि नामों के आधार पर एक सूचक प्रकार शामिल है। तो जब आप set.Add(whatever) पर कॉल करते हैं, तो यह मूल के आंतरिक डेटा को बदल देगा।

3

Calls, The Go Programming Language Specification

एक समारोह कॉल में, समारोह मूल्य और तर्क सामान्य क्रम में मूल्यांकन कर रहे हैं। उनके मूल्यांकन के बाद, कॉल के पैरामीटर फ़ंक्शन के मान द्वारा पारित किए जाते हैं और कॉल किया गया फ़ंक्शन निष्पादन शुरू होता है। फ़ंक्शन के रिटर्न पैरामीटर मान द्वारा फ़ंक्शन लौटने पर कॉलिंग फ़ंक्शन पर वापस भेजे जाते हैं।

When are function parameters passed by value? FAQ - The Go Programming Language.

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

मानचित्र और टुकड़ा मूल्यों संकेत की तरह व्यवहार करते हैं: वे वर्णनकर्ता कि अंतर्निहित नक्शा या टुकड़ा आंकड़ों के संकेत दिए गए होते हैं। मानचित्र या स्लाइस मान की प्रतिलिपि बनाने से डेटा को कॉपी नहीं किया जाता है। इंटरफेस की प्रतिलिपि मान इंटरफ़ेस मान में संग्रहीत चीज़ की एक प्रति बनाता है। यदि इंटरफ़ेस मान एक संरचना रखता है, तो इंटरफ़ेस मान की प्रतिलिपि बनाना संरचना की प्रति बनाता है। यदि इंटरफ़ेस मान में पॉइंटर होता है, तो कॉपी करना इंटरफ़ेस मान पॉइंटर की एक प्रति बनाता है, लेकिन फिर यह डेटा इंगित करता है।

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