2010-05-02 20 views
6

जब आप मूल्य या पॉइंटर द्वारा किसी अन्य संरचना तक पहुंचते हैं तो क्या अंतर होता है?
उनमें से प्रत्येक का उपयोग कब किया जाना चाहिए?मूल्य या पॉइंटर द्वारा अन्य संरचना तक पहुंच

type foo_ struct { 
    st uint8 
    nd uint8 
} 

type bar struct { 
    rd uint8 
    foo foo_ 
} 

type barP struct { 
    rd uint8 
    foo *foo_ 
} 

उत्तर

5

यदि आप type bar के चर को घोषित या आवंटित करते हैं, तो आप rd uint8 और foo foo_ दोनों के लिए शून्य स्मृति को आरक्षित और प्रारंभ करते हैं। का एक चर हमेशा type bar के चर में एम्बेड किया गया है।

var b bar // declare b 

आप यह घोषणा करते या type barP के एक चर आवंटित हैं, तो आप को आरक्षित और rd uint8 और foo *foo_ दोनों के लिए शून्य स्मृति को आरंभ कर देगा। शून्य मान सूचक एक nil सूचक है। type foo_ का कोई चर आवंटित नहीं किया गया है; आपको इसे अलग से करना होगा। या तो शून्य (foo == nil) या type foo_ का एक चर है जो type barP के चर द्वारा इंगित किया गया है। type barP का एक चर type foo_ के समान चर को type barP के अन्य चर के रूप में इंगित कर सकता है, type foo_ के चर की एक ही प्रति साझा करना। एक साझा प्रति में परिवर्तन सभी चर द्वारा देखा जाता है जो इसे इंगित करता है।

var bp barP   // declare bp 
bp.foo = new(foo_) // allocate bp.foo 

कौन सा उपयोग करने के लिए type bar बनाम type barP के गुणों पर निर्भर करता है। कौन सा प्रकार हल करने की कोशिश कर रहे समस्या को अधिक बारीकी से दर्शाता है?

उदाहरण के लिए, इस चालान समस्या पर विचार करें। हमारे पास हमेशा एक बिलिंग पता होता है; हम हमेशा हमारे पैसे मांगने जा रहे हैं। हालांकि, हम अक्सर बिलिंग पते पर जाते हैं, लेकिन हमेशा नहीं। यदि शिपिंग पता nil है, तो बिलिंग पता का उपयोग करें। अन्यथा, एक अलग शिपिंग पता का उपयोग करें। हमारे पास दो गोदाम हैं, और हम हमेशा एक या दूसरे से जहाज भेजते हैं। हम दो गोदामों के स्थान साझा कर सकते हैं। चूंकि हम गोदाम से आदेश भेज दिए जाने तक चालान नहीं भेजते हैं, इसलिए गोदाम का स्थान कभी भी nil नहीं होगा।

type address struct { 
    street string 
    city string 
} 

type warehouse struct { 
    address string 
} 

type invoice struct { 
    name  string 
    billing address 
    shipping *address 
    warehouse *warehouse 
} 
2

उत्तर भाषा से काफी हद तक स्वतंत्र है - सी में समकक्ष समान समस्याएं हैं।

जब आपके पास एक एम्बेडेड वैल्यू है (bar में), तो आपकी संरचना पूरी उप-संरचना और दूसरे भाग को पकड़ने के लिए काफी बड़ी है।

आप (barP के रूप में) एक मूल्य के लिए सूचक है, तो प्रकार barP के ढांचे के एक नंबर एक ही foo साझा कर सकते हैं। जब barP में से कोई भी foo का एक हिस्सा संशोधित करता है, तो यह इंगित करता है कि यह अन्य सभी barP संरचनाओं को प्रभावित करता है जो एक ही स्थान पर इंगित करते हैं। साथ ही, जैसा कि टिप्पणी से पता चलता है, आपको 0 अलग-अलग ऑब्जेक्ट्स - barP और foo को सादे bar प्रकार के साथ एक के विरुद्ध प्रबंधित करना होगा।

कुछ भाषाओं में, आपको पॉइंटर्स और अनियमित मूल्यों को लटकाने के बारे में चिंता करने की आवश्यकता होगी; जाओ कचरा इकट्ठा किया जाता है और आम तौर पर अन्य भाषाओं की तुलना में अधिक प्रकार से सुरक्षित है।

तो, जब आप foo ऑब्जेक्ट को साझा करने के लिए एकाधिक barP ऑब्जेक्ट्स चाहते हैं तो पॉइंटर का उपयोग करें; अन्यथा, ऑब्जेक्ट के पॉइंटर के बजाए एक स्पष्ट सदस्य ऑब्जेक्ट का उपयोग करें।

+1

जब 'टाइप बारप' का एक चर घोषित या आवंटित किया जाता है, तो foo का प्रारंभिक मान 'शून्य' सूचक होगा। – peterSO

2

Golang FAQ अब के बीच अंतर सार रखते हैं:

func (s *MyStruct) pointerMethod() { } // method on pointer 
func (s MyStruct) valueMethod() { } // method on value 

पहले, और सबसे महत्वपूर्ण, विधि रिसीवर संशोधित करने की आवश्यकता है?
यदि ऐसा होता है, तो रिसीवर एक सूचक होना चाहिए। (स्लाइस और मानचित्र संदर्भ प्रकार हैं, इसलिए उनकी कहानी थोड़ी अधिक सूक्ष्म है, लेकिन उदाहरण के लिए एक विधि में एक टुकड़ा की लंबाई को बदलने के लिए रिसीवर अभी भी एक सूचक होना चाहिए।)
उपर्युक्त उदाहरणों में, यदि pointerMethod संशोधित करता है s के क्षेत्र, कॉलर उन परिवर्तनों को देखेगा, लेकिन valueMethod को कॉलर के तर्क की एक प्रति (जिसे मूल्य पारित करने की परिभाषा है) कहा जाता है, इसलिए इसे बदलने से कॉलर को अदृश्य हो जाएगा।
वैसे, पॉइंटर रिसीवर जावा की स्थिति के समान हैं, हालांकि जावा में पॉइंटर्स कवर के नीचे छिपे हुए हैं; यह गो के मूल्य रिसीवर है जो असामान्य हैं।

दूसरा दक्षता पर विचार है। यदि रिसीवर बड़ा है, उदाहरण के लिए एक बड़ी संरचना, पॉइंटर रिसीवर का उपयोग करना बहुत सस्ता होगा।

(यह दक्षता बिंदु भी "Memory, variables in memory, and pointers" में चित्रित किया गया है)

अगला स्थिरता है। यदि प्रकार के कुछ तरीकों में पॉइंटर रिसीवर होना चाहिए, तो बाकी भी चाहिए, इसलिए विधि सेट इस प्रकार पर ध्यान दिए बिना कि किस प्रकार का उपयोग किया जाता है। विवरण के लिए method sets पर अनुभाग देखें।

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