मैं गो में शाब्दिक * int64 कैसे करूँ?


103

मेरे पास एक *int64फ़ील्ड के साथ एक संरचनात्मक प्रकार है ।

type SomeType struct {
    SomeField *int64
}

मेरे कोड के कुछ बिंदु पर, मैं इसका एक शाब्दिक ऐलान करना चाहता हूं (कहते हैं, जब मुझे पता है कि मूल्य 0 होना चाहिए, या 0 की ओर इशारा करते हुए, आपको पता है कि मेरा क्या मतलब है)

instance := SomeType{
    SomeField: &0,
}

... इसके अलावा यह काम नहीं करता है

./main.go:xx: cannot use &0 (type *int) as type *int64 in field value

इसलिए मैं यह कोशिश करता हूं

instance := SomeType{
    SomeField: &int64(0),
}

... लेकिन यह भी काम नहीं करता है

./main.go:xx: cannot take the address of int64(0)

मैं यह कैसे करु? एकमात्र समाधान जिसके साथ मैं आ सकता हूं वह एक प्लेसहोल्डर चर का उपयोग कर रहा है

var placeholder int64
placeholder = 0

instance := SomeType{
    SomeField: &placeholder,
}

नोट: &0सिंटैक्स ठीक काम करता है जब यह एक के बजाय एक * int है *int64संपादित करें: नहीं यह नहीं है। इसके लिए क्षमा करें।

संपादित करें:

मोटे तौर पर मेरे सवाल में बहुत ज्यादा अस्पष्टता थी। मैं के लिए एक रास्ता तलाश कर रहा हूँ सचमुच राज्य एक *int64। इसका उपयोग एक कंस्ट्रक्टर के अंदर, या शाब्दिक संरचनात्मक मूल्यों को या अन्य कार्यों के लिए तर्क के रूप में भी किया जा सकता है। लेकिन सहायक कार्य या एक अलग प्रकार का उपयोग करना ऐसे समाधान नहीं हैं जिनकी मुझे तलाश है।


1
Int के लिए पॉइंटर्स दुर्भाग्यपूर्ण हैं क्योंकि int एक पॉइंटर के समान जगह लेता है, इसलिए आप स्पेस को नहीं बचा रहे हैं। यह सिर्फ एक NULL वैल्यू जोड़ता है जो आमतौर पर मूल्य की तुलना में केवल अधिक जटिलता है। ज्यादातर मामलों में एक 0 ठीक होगा। यदि आपको अतिरिक्त मूल्य की आवश्यकता है तो "IsValidSomeField" बूल भी काम करता है और यदि आप उस बूल को एक बेहतर नाम देते हैं तो यह अधिक कह सकता है कि आपको उस अतिरिक्त मूल्य की आवश्यकता क्यों है, जो पठनीयता के लिए अच्छा है।
वौतासोरस

2
आप पैकेज पॉइंटर का उपयोग कर सकते हैं , उदाहरण के लिए:var _ *int64 = pointer.Int64(64)
Xor

जवाबों:


212

गो लैंग्वेज स्पेसिफिकेशन ( पता ऑपरेटर ) एक संख्यात्मक स्थिरांक का पता लेने की अनुमति नहीं देता है (न तो अप्रकाशित और न ही टाइप किए गए स्थिरांक की)।

ऑपरेंड को पता योग्य होना चाहिए , अर्थात, एक चर, सूचक अप्रत्यक्ष, या स्लाइस इंडेक्सिंग ऑपरेशन; या एक पता योग्य संरचना के क्षेत्र का चयनकर्ता; या किसी पता योग्य सरणी का एक सरणी अनुक्रमण ऑपरेशन। पते की आवश्यकता के अपवाद के रूप में, x[की अभिव्यक्ति में &x] एक भी हो सकता है (संभवतः कोष्ठबद्ध) समग्र शाब्दिक

तर्क के लिए यह अनुमति क्यों नहीं है, संबंधित प्रश्न देखें: जाने में निरंतर का पता लगाएं । एक समान प्रश्न (इसी तरह इसका पता लेने की अनुमति नहीं है): मैं गो में एक ऑपरेशन के परिणाम के संदर्भ को कैसे स्टोर कर सकता हूं?

आपके विकल्प (सभी खेल के मैदान पर प्रयास करें ):

1) के साथ new()

आप बस new()एक नया शून्य- मान आवंटित करने int64और उसका पता प्राप्त करने के लिए बिल्टिन फ़ंक्शन का उपयोग कर सकते हैं :

instance := SomeType{
    SomeField: new(int64),
}

लेकिन ध्यान दें कि इसका उपयोग किसी भी प्रकार के शून्य मान को इंगित करने और प्राप्त करने के लिए किया जा सकता है।

2) सहायक चर के साथ

गैर-शून्य तत्वों के लिए सरल और अनुशंसित एक सहायक चर का उपयोग करना है जिसका पता लिया जा सकता है:

helper := int64(2)
instance2 := SomeType{
    SomeField: &helper,
}

3) सहायक समारोह के साथ

नोट: एक गैर-शून्य मान के लिए एक पॉइंटर प्राप्त करने के लिए हेल्पर फ़ंक्शंस मेरी github.com/icza/goxलाइब्रेरी में, goxपैकेज में उपलब्ध हैं , इसलिए आपको इन सभी को अपनी सभी परियोजनाओं में शामिल करने की ज़रूरत नहीं है जहाँ आपको इसकी आवश्यकता है।

या यदि आपको कई बार इसकी आवश्यकता होती है, तो आप एक सहायक फ़ंक्शन बना सकते हैं जो आवंटित करता है और एक रिटर्न देता है *int64:

func create(x int64) *int64 {
    return &x
}

और इसका उपयोग कर रहे हैं:

instance3 := SomeType{
    SomeField: create(3),
}

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

4) एक-लाइनर अनाम फ़ंक्शन के साथ

instance4 := SomeType{
    SomeField: func() *int64 { i := int64(4); return &i }(),
}

या एक (कम) विकल्प के रूप में:

instance4 := SomeType{
    SomeField: func(i int64) *int64 { return &i }(4),
}

5) स्लाइस शाब्दिक, अनुक्रमण और पते के साथ

यदि आप के *SomeFieldअलावा अन्य होना चाहते हैं 0, तो आपको कुछ पता करने की आवश्यकता है।

आप अभी भी ऐसा कर सकते हैं, लेकिन यह बदसूरत है:

instance5 := SomeType{
    SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5

यहां क्या होता है एक []int64टुकड़ा एक शाब्दिक के साथ बनाया जाता है, जिसमें एक तत्व ( 5) होता है। और इसे अनुक्रमित (0 तत्व) किया जाता है और 0 तत्व का पता लिया जाता है। पृष्ठभूमि में [1]int64वसीयत की एक सरणी भी आवंटित की जाएगी और स्लाइस के लिए बैकिंग ऐरे के रूप में उपयोग की जाएगी। इसलिए यहां बहुत अधिक बॉयलरप्लेट है।

6) एक सहायक संरचनात्मक शाब्दिक के साथ

आइए अपवाद की आवश्यकताओं के अपवाद की जांच करें:

पते की आवश्यकता के अपवाद के रूप में, x[की अभिव्यक्ति में &x] एक भी हो सकता है (संभवतः कोष्ठबद्ध) समग्र शाब्दिक

इसका मतलब है कि एक समग्र शाब्दिक का पता, उदाहरण के लिए एक संरचनात्मक शाब्दिक ठीक है। यदि हम ऐसा करते हैं, तो हमारे पास आवंटित मूल्य और इसके लिए प्राप्त एक सूचक होगा। लेकिन अगर ऐसा है, तो एक और आवश्यकता हमारे लिए उपलब्ध हो जाएगी: "एक पता योग्य संरचनात्मक ऑपरेंड का क्षेत्र चयनकर्ता" । तो अगर स्ट्रक्चर शाब्दिक में फ़ील्ड का प्रकार होता है int64, तो हम उस फ़ील्ड का पता भी ले सकते हैं!

इस विकल्प को कार्रवाई में देखते हैं। हम इस आवरण संरचना प्रकार का उपयोग करेंगे:

type intwrapper struct {
    x int64
}

और अब हम कर सकते हैं:

instance6 := SomeType{
    SomeField: &(&intwrapper{6}).x,
}

ध्यान दें कि यह

&(&intwrapper{6}).x

निम्नलिखित का अर्थ है:

& ( (&intwrapper{6}).x )

लेकिन हम "बाहरी" कोष्ठक को छोड़ सकते हैं &क्योंकि चयनकर्ता अभिव्यक्ति चयनकर्ता के परिणाम पर लागू होता है ।

यह भी ध्यान दें कि पृष्ठभूमि में निम्नलिखित होगा (यह एक मान्य वाक्यविन्यास भी है):

&(*(&intwrapper{6})).x

7) सहायक गुमनाम संरचनात्मक शाब्दिक के साथ

केस # 6 के साथ सिद्धांत समान है, लेकिन हम एक अनाम संरचना शाब्दिक का भी उपयोग कर सकते हैं, इसलिए कोई सहायक / आवरण संरचना प्रकार की परिभाषा की आवश्यकता नहीं है:

instance7 := SomeType{
    SomeField: &(&struct{ x int64 }{7}).x,
}

1
यह प्लेसहोल्डर के साथ प्रश्न में अंतिम उदाहरण से कार्यात्मक रूप से अलग है, क्योंकि instanceदो अलग-अलग ऑब्जेक्ट दो अलग-अलग int64एस को इंगित करेंगे । लेकिन यह पर्याप्त रूप से ओपी के इरादे को पूरा करता प्रतीत होता है
रियान हेनिंग

2
यह निश्चित रूप से मेरे सवाल का जवाब देता है। लेकिन यह मुझे काफी परेशान करता है: &[]int64{2}[0]मुझे ऐसा लगता है कि blog.golang.org/constants पर स्थिरांक के विवरण के आधार पर यह काम करना चाहिए&0
ThisGuy

@RyanHaining और क्या होगा अगर यह उसी तरह काम करेगा जैसे पता सौंपा जाएगा? यदि दो अलग-अलग instanceऑब्जेक्ट int64एक ही ओर इंगित करते हैं और एक इंगित ऑब्जेक्ट को संशोधित करेगा, तो दोनों बदल जाएंगे। और क्या होगा अगर अब आप उसी शाब्दिक का उपयोग 3rd बनाने के लिए करते हैं instance? एक ही पता अब एक अलग int64मूल्य की ओर इशारा करता है ... इसलिए एक अलग पते का उपयोग किया जाना चाहिए, लेकिन फिर पहले 2 के मामले में समान का उपयोग क्यों करें?
19

@icza आप आमतौर पर उन्हें एक ही वस्तु की ओर इशारा नहीं करना चाहेंगे, मैं यह नहीं कह रहा हूँ कि आप करेंगे। मैं सिर्फ अंतर की ओर इशारा कर रहा हूं।
रियान हेनिंग

4
@ कोंसलो स्थिरांक का संकलन समय पर किया जाता है। एक मान्य पॉइंटर मान, एक मान्य मेमोरी पता केवल रनटाइम पर मौजूद होता है, इसलिए यह स्थिरांक के समान नहीं है।
icza

6

एक फ़ंक्शन का उपयोग करें जो समस्या को हल करने के लिए एक int64 चर का पता लौटाता है।

नीचे दिए गए कोड में हम फ़ंक्शन का उपयोग करते हैं fजो पूर्णांक को स्वीकार करता है और एक सूचक मान देता है जो पूर्णांक का पता रखता है। इस विधि का उपयोग करके हम आसानी से उपरोक्त समस्या को हल कर सकते हैं।

type myStr struct {
    url *int64
}

func main() {
    f := func(s int64) *int64 {
        return &s
    }
    myStr{
        url: f(12345),
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.