गो में एनआईएल का पता लगाना


165

मुझे इस तरह का पता लगाने के लिए Go में बहुत सारे कोड दिखाई देते हैं:

if err != nil { 
    // handle the error    
}

हालाँकि, मेरे पास इस तरह की एक संरचना है:

type Config struct {
    host string  
    port float64
}

और विन्यास विन्यास का एक उदाहरण है, जब मैं करता हूं:

if config == nil {
}

यह कहते हुए संकलित त्रुटि है: विन्यास टाइप करने के लिए शून्य में परिवर्तित नहीं कर सकते


3
मुझे समझ नहीं आया कि पोर्ट फ्लोट64 का क्यों है?
अलामिन

2
यह नहीं होना चाहिए। गो के JSON एपि JSON से किसी भी संख्या को फ्लोट64 में आयात करता है, मुझे फ्लोट64 को इंट में बदलना है।
कियान चेन

जवाबों:


179

संकलक आपको त्रुटि इंगित कर रहा है, आप संरचना उदाहरण और शून्य की तुलना कर रहे हैं। वे एक ही प्रकार के नहीं हैं इसलिए यह इसे एक अवैध तुलना के रूप में मानता है और आप पर चिल्लाता है।

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

config := new(Config) // not nil

या

config := &Config{
                  host: "myhost.com", 
                  port: 22,
                 } // not nil

या

var config *Config // nil

तब आप जांच कर पाएंगे कि क्या

if config == nil {
    // then
}

5
मुझे लगता है कि var config &Config // nilहोना चाहिए:var config *Config
टॉमस प्लान्का

var config *Configके साथ क्रैश invalid memory address or nil pointer dereference। शायद हमें जरूरत हैvar config Config
कचहर

मैं समझता हूं कि इस पसंद के पीछे का तर्क आपका नहीं हो सकता है, लेकिन इससे मुझे कोई मतलब नहीं है कि "अगर! (Config! = Nil)" वैध है, लेकिन यह "if config == nil" नहीं है। दोनों समान संरचना और गैर-संरचना के बीच तुलना कर रहे हैं।
retorquere

@retorquere वे दोनों अमान्य हैं, play.golang.org/p/k2EmRcels6 देखें । चाहे वह '! =' या '==' कोई फर्क नहीं पड़ता; क्या फर्क पड़ता है कि क्या कॉन्फिगरेशन स्ट्रक्चर के लिए पॉइंटर या पॉइंटर है।
स्टूअबेसिक

मुझे लगता है कि यह गलत है, क्योंकि यह हमेशा गलत है: play.golang.org/p/g-MdbEbnyNx
Madeo

61

ओलीडे के अलावा, शून्य मानों पर युक्ति देखें :

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

जैसा कि आप देख सकते हैं, nilहर प्रकार के लिए शून्य मान नहीं है, लेकिन केवल पॉइंटर्स, फ़ंक्शंस, इंटरफेस, स्लाइस, चैनल और मैप्स के लिए। यही कारण है कि config == nilएक त्रुटि है और &config == nilनहीं है।

यह जांचने के लिए कि क्या आपके struct अप्रारंभीकृत है आप अपने संबंधित शून्य मान के लिए हर सदस्य की जांच करना होगा (जैसे host == "", port == 0, आदि) या एक निजी क्षेत्र जो एक आंतरिक प्रारंभ विधि से सेट किया गया है। उदाहरण:

type Config struct {
    Host string  
    Port float64
    setup bool
}

func NewConfig(host string, port float64) *Config {
    return &Config{host, port, true}
}

func (c *Config) Initialized() bool { return c != nil && c.setup }

4
इसके बाद के संस्करण के लिए, यही कारण है कि time.Timeएक IsZero()विधि है। हालाँकि आप भी कर सकते हैं var t1 time.Time; if t1 == time.Time{}और आप अपने लिए सभी क्षेत्र की जाँच करने के लिए भी कर सकतेif config == Config{} हैं (संरचना समानता गो में अच्छी तरह से परिभाषित है)। हालाँकि, यह कारगर नहीं है यदि आपके पास बहुत सारे क्षेत्र हैं। और, शायद शून्य मान एक विशेष और प्रयोग करने योग्य मूल्य है, जो विशेष नहीं है।
डेव सी

1
प्रारंभिक फ़ंक्शन विफल हो जाएगा, अगर एक पॉइंटर के रूप में कॉन्फ़िगर किया गया है। इसे परिवर्तित किया जा सकता हैfunc (c *Config) Initialized() bool { return !(c == nil) }
सुंदर

इस मामले में @Sundar यह इस तरह से करना सुविधाजनक हो सकता है, इसलिए मैंने बदलाव लागू किया। हालांकि, आमतौर पर मैं यह जांचने के लिए विधि कॉल के प्राप्त होने की उम्मीद नहीं करूंगा कि क्या यह शून्य है, क्योंकि यह कॉलर का काम होना चाहिए।
नीमो

16

मैंने कुछ सैंपल कोड बनाए हैं जो विभिन्न प्रकारों का उपयोग करके नए चर बनाता है जिनके बारे में मैं सोच सकता हूं। ऐसा लगता है कि पहले 3 तरीके मूल्य बनाते हैं, और अंतिम दो संदर्भ बनाते हैं।

package main

import "fmt"

type Config struct {
    host string
    port float64
}

func main() {
    //value
    var c1 Config
    c2 := Config{}
    c3 := *new(Config)

    //reference
    c4 := &Config{}
    c5 := new(Config)

    fmt.Println(&c1 == nil)
    fmt.Println(&c2 == nil)
    fmt.Println(&c3 == nil)
    fmt.Println(c4 == nil)
    fmt.Println(c5 == nil)

    fmt.Println(c1, c2, c3, c4, c5)
}

कौन से आउटपुट:

false
false
false
false
false
{ 0} { 0} { 0} &{ 0} &{ 0}

6

आप भी चेक कर सकते हैं struct_var == (struct{})। यह आपको शून्य की तुलना करने की अनुमति नहीं देता है लेकिन यह जांच करता है कि यह आरंभीकृत है या नहीं। इस विधि का उपयोग करते समय सावधान रहें। यदि आपकी संरचना में इसके सभी क्षेत्रों के लिए शून्य मान हो सकते हैं तो आपके पास बहुत अच्छा समय नहीं होगा।

package main

import "fmt"

type A struct {
    Name string
}

func main() {
    a := A{"Hello"}
    var b A

    if a == (A{}) {
        fmt.Println("A is empty") // Does not print
    } 

    if b == (A{}) {
        fmt.Println("B is empty") // Prints
    } 
}

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


3

भाषा कल्पना का उल्लेख तुलना ऑपरेटरों 'व्यवहार:

तुलना ऑपरेटरों

किसी भी तुलना में, पहले ऑपरेंड को दूसरे ऑपरेंड के प्रकार के लिए, या इसके विपरीत होना चाहिए।


Assignability

एक मान x टाइप टी के एक चर के लिए ("एक्स के लिए असाइन करने योग्य है") इनमें से किसी भी मामले में है:

  • x का प्रकार T के समान है।
  • x के प्रकार V और T में अंतर्निहित अंतर्निहित प्रकार हैं और कम से कम V या T में से एक नाम प्रकार नहीं है।
  • T एक इंटरफ़ेस प्रकार है और x औजार T है।
  • x एक द्विदिश चैनल मान है, T एक चैनल प्रकार है, x का प्रकार V और T में समान तत्व प्रकार है, और V या T में से कम से कम एक नामित प्रकार नहीं है।
  • x पूर्वनिर्धारित पहचानकर्ता nil है और T एक पॉइंटर, फंक्शन, स्लाइस, मैप, चैनल या इंटरफ़ेस प्रकार है।
  • X, T के मान द्वारा एक अप्रमाणित स्थिर अभ्यावेदन है।

0

1.13 और बाद में, आप पैकेज Value.IsZeroमें दी गई विधि का उपयोग कर सकते हैं reflect

if reflect.ValueOf(v).IsZero() {
    // v is zero, do something
}

बुनियादी प्रकारों के अलावा, यह ऐरे, चान, फंक, इंटरफेस, मैप, Ptr, Slice, UnsafePointer और स्ट्रक्चर के लिए भी काम करता है। इसे संदर्भ के लिए देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.