एक खाली संरचना की जांच कैसे करें?


110

मैं एक संरचना को परिभाषित करता हूं ...

type Session struct {
    playerId string
    beehive string
    timestamp time.Time
}

कभी-कभी मैं इसे एक खाली सत्र सौंपता हूं (क्योंकि शून्य संभव नहीं है)

session = Session{};

फिर मैं जांच करना चाहता हूं, अगर यह खाली है:

if session == Session{} {
     // do stuff...
}

जाहिर है कि यह काम नहीं कर रहा है। मैं इसे कैसे लिखूं?


4
सत्र {} एक "खाली" सत्र नहीं है; यह प्रत्येक क्षेत्र में शून्य मान होने के साथ आरंभिक है।
पॉल हैंकिन

जवाबों:


177

आप शून्य मानों के साथ तुलना करने के लिए == का उपयोग कर सकते हैं, क्योंकि सभी क्षेत्र तुलनीय हैं :

if (Session{}) == session  {
    fmt.Println("is zero value")
}

खेल का मैदान उदाहरण

एक की वजह से पार्स करने अस्पष्टता , कोष्ठक अगर हालत में समग्र शाब्दिक के आसपास की आवश्यकता है।

==ऊपर का उपयोग उन संरचनाओं पर लागू होता है जहां सभी क्षेत्र तुलनीय हैं । यदि संरचना में एक गैर-तुलनीय क्षेत्र (टुकड़ा, नक्शा या फ़ंक्शन) होता है, तो फ़ील्ड की तुलना एक-एक करके उनके शून्य मान से की जानी चाहिए।

संपूर्ण मान की तुलना करने का एक विकल्प उस क्षेत्र की तुलना करना है जिसे एक वैध सत्र में गैर-शून्य मान पर सेट किया जाना चाहिए। उदाहरण के लिए, यदि खिलाड़ी आईडी मान्य सत्र में होना चाहिए! = ""

if session.playerId == "" {
    fmt.Println("is zero value")
}

4
@ क्रिस्टेन पॉइंटर को पॉइंटर करें और तुलना करें यदि sessionएक गैर-शून्य है *Session, तो उपयोग करें if (Session{} == *session {
मफिन टॉप

3
तो मुझे एक त्रुटि मिलती है struct containing []byte cannot be compared, क्योंकि, ठीक है, मेरी संरचना में एक बाइट टुकड़ा है।
कदापि नहीं

14
@Nevermore तुलनीय क्षेत्रों के साथ एक संरचना पर जवाब लागू होता है। यदि आपकी संरचना में [] बाइट जैसे गैर-तुलनीय मूल्य हैं, तो आपको सभी क्षेत्रों का परीक्षण करने के लिए कोड लिखने या किसी अन्य उत्तर में उल्लिखित प्रतिबिंबित पैकेज का उपयोग करने की आवश्यकता है।
मफिन टॉप

2
जैसा कि @Nevermore द्वारा उल्लेख किया गया है, ==स्लाइस फ़ील्ड के साथ तुलना विफल हो जाएगी। इन संरचनाओं की तुलना करने के लिए, reflect.DeepEqualया तो उपयोग किए गए या कुछ और विशेष पर विचार करें जैसे कि यहां चर्चा की गई है: stackoverflow.com/questions/24534072/…
5

"अगर स्थिति में अस्पष्टता पार्सिंग" ने मेरा दिन बचाया, धन्यवाद :) coz जब मैं इसे fmt में देख रहा था। क्रिंचलन (सत्र == सत्र {}), यह काम करता है।
23

37

यहाँ 3 और सुझाव या तकनीकें दी गई हैं:

एक अतिरिक्त क्षेत्र के साथ

आप यह बताने के लिए एक अतिरिक्त फ़ील्ड जोड़ सकते हैं कि क्या संरचना आबाद हो गई है या वह खाली है। मैंने जानबूझकर इसे नाम दिया है readyऔर emptyइसलिए नहीं कि शून्य का मान boolहै false, इसलिए यदि आप एक नया ढांचा बनाते हैं जैसे कि Session{}इसका readyक्षेत्र अपने आप हो जाएगा falseऔर यह आपको सच बताएगा: कि संरचना अभी तक तैयार नहीं है (यह खाली है)।

type Session struct {
    ready bool

    playerId string
    beehive string
    timestamp time.Time
}

जब आप संरचना को शुरू करते हैं, तो आपको सेट readyकरना होगा true। आपकी isEmpty()विधि की अब और आवश्यकता नहीं है (हालाँकि आप चाहें तो एक बना सकते हैं) क्योंकि आप केवल readyक्षेत्र का परीक्षण कर सकते हैं ।

var s Session

if !s.ready {
    // do stuff (populate s)
}

यह एक अतिरिक्त boolक्षेत्र का महत्व बढ़ जाता है क्योंकि संरचना बड़ी हो जाती है या यदि इसमें ऐसे क्षेत्र होते हैं जो तुलनीय नहीं होते हैं (जैसे टुकड़ा, mapऔर फ़ंक्शन मान)।

मौजूदा क्षेत्र के शून्य मान का उपयोग करना

यह पिछले सुझाव के समान है, लेकिन यह मौजूदा फ़ील्ड के शून्य मान का उपयोग करता है जिसे तब माना जाता है जब संरचना खाली न हो। इस की प्रयोज्यता कार्यान्वयन पर निर्भर है।

उदाहरण के लिए यदि आपके उदाहरण में आपका playerIdस्थान रिक्त नहीं हो सकता है string "", तो आप इसका उपयोग यह जांचने के लिए कर सकते हैं कि क्या आपकी संरचना इस प्रकार रिक्त है:

var s Session

if s.playerId == "" {
    // do stuff (populate s, give proper value to playerId)
}

इस मामले में इस जाँच को एक isEmpty()विधि में शामिल करने लायक है क्योंकि यह जाँच कार्यान्वयन पर निर्भर है:

func (s Session) isEmpty() bool {
    return s.playerId == ""
}

और इसका उपयोग करते हुए:

if s.isEmpty() {
    // do stuff (populate s, give proper value to playerId)
}

अपनी संरचना के लिए पॉइंटर का उपयोग करें

दूसरा सुझाव आपकी संरचना के लिए एक सूचक का उपयोग करना है *Session:। संकेत में nilमान हो सकते हैं , इसलिए आप इसके लिए परीक्षण कर सकते हैं:

var s *Session

if s == nil {
    s = new(Session)
    // do stuff (populate s)
}

बहुत बढ़िया जवाब। धन्यवाद, इक्जा!
एवगेनी गोल्डिन

बहुत बढ़िया जवाब! मुझे लगता है कि अंतिम विकल्प का पालन करना बहुत मुहावरेदार लगता है।
डेविंसनटेजेडा

19

Reflect.deepEqual का उपयोग करना भी काम करता है , खासकर जब आपके पास संरचना के अंदर नक्शा होता है

package main

import "fmt"
import "time"
import "reflect"

type Session struct {
    playerId string
    beehive string
    timestamp time.Time
}

func (s Session) IsEmpty() bool {
  return reflect.DeepEqual(s,Session{})
}

func main() {
  x := Session{}
  if x.IsEmpty() {
    fmt.Print("is empty")
  } 
}

2
परावर्तक का उपयोग करना। डीपक्वेल एक बहुत ही स्वच्छ समाधान है लेकिन मुझे आश्चर्य है कि अगर यह अधिक प्रसंस्करण समय लेता है? मुझे लगता है कि यह हर क्षेत्र की तुलना कर रहा है, साथ ही आप एक नया आयात शुरू करते हैं।
thurt

4

ध्यान रखें कि पॉइंटर्स टू स्ट्रक्चर के लिए आपको वैरिएबल को डीरेफर करना होगा और इसकी तुलना पॉइंटर से खाली स्ट्रक्चर से नहीं करनी चाहिए:

session := &Session{}
if (Session{}) == *session {
    fmt.Println("session is empty")
}

इस खेल के मैदान की जाँच करें ।

यहाँ भी आप देख सकते हैं कि एक संपत्ति जो कि एक पॉइंट है जो पॉइंटर्स का एक टुकड़ा है उसी तरह से तुलना नहीं की जा सकती ...


0

अन्य उत्तरों के विकल्प के रूप में, यह सिंटैक्स के साथ ऐसा करना संभव है जिस तरह से आप मूल रूप से इरादा करते हैं यदि आप इसे एक caseबयान के बजाय एक के माध्यम से करते हैं if:

session := Session{}
switch {
case Session{} == session:
    fmt.Println("zero")
default:
    fmt.Println("not zero")
}

खेल का मैदान उदाहरण


0

बस एक त्वरित जोड़, क्योंकि मैंने आज उसी मुद्दे को निपटाया:

1.13 गो के साथ नई isZero()विधि का उपयोग करना संभव है :

if reflect.ValueOf(session).IsZero() {
     // do stuff...
}

मैंने प्रदर्शन के संबंध में यह परीक्षण नहीं किया, लेकिन मुझे लगता है कि यह तुलना के मुकाबले तेज़ होना चाहिए reflect.DeepEqual()


-1

की तरह हो सकता है कि कुछ इस

package main

import "fmt"
import "time"

type Session struct {
    playerId string
    beehive string
    timestamp time.Time
}

func (s Session) Equal(o Session) bool {
   if(s.playerId != o.playerId) { return false }
   if(s.beehive != o.beehive) { return false }
   if(s.timestamp != o.timestamp) { return false }
   return true
}

func (s Session) IsEmpty() bool {
    return s.Equal(Session{})
}

func main() {
    x := Session{}
    if x.IsEmpty() {
       fmt.Print("is empty")
    } 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.