Go में पॉइंटर्स होने की क्या बात है?


100

मुझे पता है कि Go में संकेत किसी फ़ंक्शन के तर्कों का म्यूटेशन करने की अनुमति देते हैं, लेकिन यह आसान नहीं होता अगर वे सिर्फ संदर्भ (उपयुक्त कास्ट या म्यूटेबल क्वालीफायर के साथ) को अपनाते। अब हमारे पास पॉइंटर्स हैं और कुछ बिल्ट-इन टाइप्स जैसे कि मैप्स और चैनल्स के निहितार्थ संदर्भ से गुजरते हैं।

क्या मुझे कुछ याद आ रहा है या केवल एक अनावश्यक जटिलता में जाने के संकेत हैं?


1
यहाँ एक प्रश्न है जो स्पष्ट करने में मदद कर सकता है: stackoverflow.com/questions/795160/… मूल्य के संदर्भों को पास करने और संदर्भ द्वारा सही मायने में पारित करने के बीच अंतर है।
आर। मार्टिनो फर्नांडीस

1
नोट: सवाल जावा के बारे में है, लेकिन यह यहाँ भी लागू होता है।
आर। मार्टिनो फर्नांडीस

1
"और कुछ बिल्ट-इन प्रकारों जैसे कि नक्शे और चैनल के निहितार्थ संदर्भ से गुजरते हैं।" नहीं, गो में सब कुछ पास-बाय-वैल्यू है। कुछ प्रकार हैं (अनौपचारिक रूप से वर्णित) संदर्भ प्रकार, क्योंकि उनमें आंतरिक परिवर्तनशील स्थिति है।
newacct

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

जवाबों:


36

मुझे वास्तव में http://www.golang-book.com/8 से लिया गया उदाहरण पसंद है

func zero(x int) {
    x = 0
}
func main() {
    x := 5
    zero(x)
    fmt.Println(x) // x is still 5
}

इसके विपरीत

func zero(xPtr *int) {
    *xPtr = 0
}
func main() {
    x := 5
    zero(&x)
    fmt.Println(x) // x is 0
}

42
सवाल यह था कि "हमारे पास संदर्भों के बजाय संकेत क्यों हैं " और मुझे समझ में नहीं आता है कि यह उदाहरण संदर्भों के साथ काम क्यों नहीं करेगा।
आंद्रेकेआर

@AndreKR क्योंकि हम चुन सकते हैं कि क्या संदर्भ द्वारा पारित किया जाए या मूल्य से पारित किया जाए। कुछ उदाहरण हैं जहां दोनों वांछनीय हो सकते हैं।
JDSweetBeat

9
@DJMethaneMan यह "पॉइंटर्स बनाम संदर्भ" है, न कि "पॉइंटर्स बनाम पास-बाय-वैल्यू"!
आंद्रेकेआर

साइड कमेंट के रूप में, "रिफ" कीवर्ड के माध्यम से C # 2.0 में पास-दर-संदर्भ जोड़ा गया। बेशक संकेत कुछ मामलों में अभी भी अधिक सुविधाजनक हैं, क्योंकि हमारे पास सूचक से सूचक तक संकेत हो सकता है ...
रॉबी प्रशंसक

मुझे नहीं लगता कि गो को सबसे लोकप्रिय भाषाओं में से एक माना जाता है और फिर भी उनमें ऐसी "विशेषता" होती है ... यह भ्रामक है और अनावश्यक लगता है, कम से कम लोगों को यह इंगित करता है।
अकीतो

33

पॉइंटर्स कई कारणों से उपयोगी हैं। पॉइंटर्स मेमोरी लेआउट पर नियंत्रण की अनुमति देते हैं (सीपीयू कैश की दक्षता को प्रभावित करता है)। गो में हम एक संरचना को परिभाषित कर सकते हैं जहाँ सभी सदस्य सन्निहित स्मृति में हैं:

type Point struct {
  x, y int
}

type LineSegment struct {
  source, destination Point
}

इस मामले में Pointसंरचना के भीतर संरचनाएं अंतर्निहित हैं LineSegment। लेकिन आप हमेशा सीधे डेटा एम्बेड नहीं कर सकते। यदि आप बाइनरी ट्री या लिंक्ड सूची जैसी संरचनाओं का समर्थन करना चाहते हैं, तो आपको किसी प्रकार के सूचक का समर्थन करने की आवश्यकता है।

type TreeNode {
  value int
  left  *TreeNode
  right *TreeNode
}

Java, Python आदि को यह समस्या नहीं है क्योंकि यह आपको समग्र प्रकारों को एम्बेड करने की अनुमति नहीं देता है, इसलिए एम्बेडिंग और पॉइंटिंग के बीच वाक्यविन्यास अंतर करने की कोई आवश्यकता नहीं है।

गो पॉइंटर्स के साथ स्विफ्ट / सी # स्ट्रक्चर वाले मुद्दे हल किए गए

एक संभावित विकल्प ही पूरा करने के लिए के बीच अंतर करने के लिए है structऔर classसी # और स्विफ्ट करता है। लेकिन इसकी सीमाएं हैं। यद्यपि आप आमतौर पर निर्दिष्ट कर सकते हैं कि कोई फ़ंक्शन संरचना की inoutप्रतिलिपि बनाने से बचने के लिए पैरामीटर के रूप में एक संरचना लेता है , तो यह आपको संदर्भों (पॉइंटर्स) को संरचित करने की अनुमति नहीं देता है। इसका मतलब यह है कि आप एक संरचना को संदर्भ प्रकार के रूप में कभी नहीं मान सकते हैं जब आप एक पूल आवंटनकर्ता बनाने के लिए उस उपयोगी उदाहरण को पाते हैं (नीचे देखें)।

कस्टम मेमोरी एलोकेटर

पॉइंटर्स का उपयोग करके आप अपना पूल आवंटनकर्ता भी बना सकते हैं (यह केवल सिद्धांत दिखाने के लिए हटाए गए बहुत सारे चेक के साथ सरल है):

type TreeNode {
  value int
  left  *TreeNode
  right *TreeNode

  nextFreeNode *TreeNode; // For memory allocation
}

var pool [1024]TreeNode
var firstFreeNode *TreeNode = &pool[0] 

func poolAlloc() *TreeNode {
    node := firstFreeNode
    firstFreeNode  = firstFreeNode.nextFreeNode
    return node
}

func freeNode(node *TreeNode) {
    node.nextFreeNode = firstFreeNode
    firstFreeNode = node
}

दो मूल्यों को स्वैप करें

पॉइंटर्स आपको लागू करने की अनुमति भी देते हैं swap। यह दो चर के मानों की अदला-बदली कर रहा है:

func swap(a *int, b *int) {
   temp := *a
   *a = *b
   *b = temp
}

निष्कर्ष

जावा कभी भी Google जैसे स्थानों पर सिस्टम प्रोग्रामिंग के लिए C ++ को पूरी तरह से बदलने में सक्षम नहीं हुआ है, क्योंकि मेमोरी लेआउट और उपयोग को नियंत्रित करने की क्षमता की कमी (कैश मिसेज प्रदर्शन को काफी प्रभावित करता है) के कारण प्रदर्शन को उसी विस्तार से नहीं जोड़ा जा सकता है। गो ने कई क्षेत्रों में C ++ को प्रतिस्थापित करने का लक्ष्य रखा है और इस तरह उसे संकेत का समर्थन करने की आवश्यकता है।


7
C # संदर्भ द्वारा संरचना को पास करने की अनुमति देता है। "Ref" और "out" कीवर्ड देखें।
ओलेज़

1
ठीक है तो यह स्विफ्ट की तरह है। मैं अपने उदाहरण को अपडेट करने के तरीके के बारे में सोचूंगा।
एरिक इंगहैम

29

संदर्भ को पुन: असाइन नहीं किया जा सकता है, जबकि संकेत कर सकते हैं। यह अकेले उन बिंदुओं को कई स्थितियों में उपयोगी बनाता है जहां संदर्भ का उपयोग नहीं किया जा सकता था।


17
क्या संदर्भ आश्वस्त हैं, भाषा-विशिष्ट कार्यान्वयन मुद्दा है।
क्रांतोक

28

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


गो प्रोग्रामिंग भाषा: भाषा डिजाइन अक्सर पूछे जाने वाले प्रश्न: क्यों मानचित्र, स्लाइस और चैनल संदर्भ हैं जबकि सरणियाँ मान हैं?

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


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


गोलंग-नट: भाषा जाओ। कुछ प्रतिक्रिया और संदेह।

"टाइप सिस्टम में const जोड़ने से यह हर जगह दिखाई देने के लिए मजबूर करता है, और किसी को हर जगह इसे हटाने के लिए मजबूर करता है अगर कुछ बदलता है। जबकि किसी तरह से अपरिवर्तनीय वस्तुओं को चिह्नित करने के लिए कुछ लाभ हो सकता है, हमें नहीं लगता कि एक कॉन्स्टेबल टाइप क्वालिफायर को रास्ता बनाना है। जाना।"


एफडब्ल्यूआईडब्ल्यू, गो में "संदर्भ प्रकार" भी आश्वस्त हैं। वे अंतर्निहित संकेत की तरह अधिक हैं?
मैट जॉइनर

1
वे केवल उन संरचनाओं के लिए विशेष वाक्यविन्यास हैं जिनमें एक सूचक (और लंबाई, क्षमता, ...) शामिल है।
mk12
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.