2012-12-20 10 views
12

यदि मैं यहजाओ: क्या मैं बहुत सारे मूल्य बना रहा हूं?

type myStruct struct { 
    mystring string 
    myint int 
} 

की तरह एक struct है और अगर मैं क्योंकि मैं पहली बार यह लौटने से पहले "एस" चर में संग्रहीत एक समारोह है कि इस

func New() myStruct { 
    s := myStruct{} 

    s.mystring = "string" 
    s.myint = 1 

    return s 
} 

की तरह एक नया myStruct देता है , क्या मेरा कार्य वास्तव में एक के बजाय 2 myStruct मान बना रहा है?

और यदि हां, तो क्या यह सुनिश्चित करने के लिए एक बेहतर अभ्यास है कि मैं इसे पहले चर में संग्रहीत नहीं करता हूं?

+0

मुझे यकीन है कि नहीं कर रहा हूँ, लेकिन मुझे याद है वहाँ की तरह एक वाक्य रचना था 'समारोह नई() (रों MyStruct) {...} 'जो आपके लिए परिणाम आवंटन करेगा। यह तेज़ हो सकता है। क्या आप Google go या gccgo का उपयोग करते हैं? –

+0

मैं Google go कमांड का उपयोग कर रहा हूं। मैं उत्सुक होगा अगर उस वाक्यविन्यास का एक ही प्रभाव होगा, या यदि यह किसी भी तरह से समस्या से बचाता है। –

+0

स्वीकृत उत्तर देखें ... इसे 'func new() (mystruct) के रूप में परिभाषित करने से आपके कंपाइलर को आपके फ़ंक्शन बॉडी में प्रवेश करने से पहले आपके लिए संरचना आवंटित करने देगी। इसे जेडीआई के जवाब के समान ही काम करना चाहिए। फिर भी आप सुनिश्चित नहीं हो सकते हैं, क्योंकि चलने के चश्मा/कार्यान्वयन स्थायी रूप से बदल रहे हैं। –

उत्तर

11

return बयान myStruct वस्तु मूल्य की एक प्रति वापस आ जाएगी। यदि यह एक छोटी वस्तु है तो यह ठीक है।

आप चाहते हैं तो फोन करने वाले इस वस्तु को संशोधित करने में सक्षम होने के लिए, और struct तरीकों कि रिसीवर के रूप में एक सूचक का उपयोग करना होगा, तो यह अधिक समझ में आता है बजाय अपने struct के सूचक के वापस जाने के लिए:

func New() *myStruct { 
    s := myStruct{} 

    s.mystring = "string" 
    s.myint = 1 

    return &s 
} 

आप प्रतिलिपि हो रहा देख सकते हैं जब आप बनाम सूचक वापसी प्रकार मूल्य की स्मृति पते की तुलना: http://play.golang.org/p/sj6mivYSHg

package main 

import (
    "fmt" 
) 

type myStruct struct { 
    mystring string 
    myint int 
} 

func NewObj() myStruct { 
    s := myStruct{} 
    fmt.Printf("%p\n", &s) 

    return s 
} 

func NewPtr() *myStruct { 
    s := &myStruct{} 
    fmt.Printf("%p\n",s) 
    return s 
} 

func main() { 

    o := NewObj() 
    fmt.Printf("%p\n",&o) 

    p := NewPtr() 
    fmt.Printf("%p\n",p) 
} 


0xf8400235a0 // obj inside NewObj() 
0xf840023580 // obj returned to caller 
0xf840023640 // ptr inside of NewPtr() 
0xf840023640 // ptr returned to caller 
+0

धन्यवाद, इस विशेष मामले में मैं एक MyStruct वापस करना चाहता हूं एक सूचक के बजाय मूल्य, लेकिन ऐसा लगता है कि आप सही हैं कि यह एक प्रतिलिपि देता है, जब तक कि मैं फ़ंक्शन हस्ताक्षर में 's' घोषित नहीं करता, जो कि अलग-अलग व्यवहार देता है। –

+0

आह हाँ, मेमोरी एड्रेस को देखकर पूरी तरह से इसे मेरे लिए साफ़ कर देता है। बहुत धन्यवाद! –

+0

हा, आपके पाइथन उत्तरों से बहुत कुछ सीखा, अब अपने गो उत्तरों से सीखना - अगर मैं कर सकता तो मैं फिर से +1 करूंगा। – RocketDonkey

3

मैं निश्चित रूप से एक गो विशेषज्ञ (या यहां तक ​​कि नौसिखिया :) नहीं) हूं, लेकिन जैसा कि @ max.haredoom का उल्लेख किया गया है, आप फ़ंक्शन हस्ताक्षर में चर आवंटित कर सकते हैं। इस तरह, आप यह भी return में s छोड़ सकते हैं:

package main 

import "fmt" 

type myStruct struct { 
    mystring string 
    myint int 
} 

func New() (s myStruct) { 
    s.mystring = "string" 
    s.myint = 1 

    return 
} 

func main() { 
    r := New() 
    fmt.Println(r) 
} 

// Outputs {string 1} 

उदाहरण है कि मैं Effective Go में सामने आने वाले में, यह इस प्रकार की चीजों को करने का सबसे आम तरीका होने लगते है, लेकिन फिर से , मैं निश्चित रूप से इस विषय पर एक अधिकार नहीं हूं (और वास्तविक प्रदर्शन पर अतिरिक्त जानकारी की तलाश करूंगा)।

+0

धन्यवाद। मुझे लगता है कि मैंने पाया कि मेरा मूल संस्करण एक प्रतिलिपि बना रहा था, लेकिन आपके संस्करण का उपयोग करके एक ही परीक्षण कर रहा है, ऐसा लगता है कि प्रतिलिपि से बचा जाता है। यहां मैंने परीक्षण किया है, लेकिन आपके समाधान के साथ अद्यतन किया गया है। http: //play.golang।संगठन/पी/66mqsVFbs_ –

+0

बस निहित रिटर्न के साथ बहुत पागल मत बनो, ज्यादातर मामलों में वे खराब अभ्यास करते हैं – jozefg

+0

@jozefg हाँ, अच्छा बिंदु :) – RocketDonkey

0

मुझे लगता है कि मुझे डिफर का उपयोग करके जवाब मिला।

मैंने फ़ंक्शन को अपडेट किया ताकि मेरास्ट्रक्चर मान में एक स्थगित संशोधन हो। इसका मतलब है कि यह वापसी के बाद होगा, लेकिन दूसरे छोर पर इसे प्राप्त करने से पहले।

जब मैं ऐसा करता हूं, तो कॉलर द्वारा प्राप्त की गई संरचना अद्यतन मूल्य नहीं दिखाती है, इसलिए ऐसा प्रतीत होता है कि मैं वास्तव में एक प्रतिलिपि वापस कर रहा हूं।

func New() myStruct { 
    s := myStruct{} 

    defer func() { 
     s.mystring = "new value" // defer an update to the value 
    }() 

    s.mystring = "string" 
    s.myint = 1 

    return s 
} 

func main() { 

    b := New() 

    fmt.Println(b) // still shows the original value 
} 

http://play.golang.org/p/WWQi8HpDny

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