1 स्ट्रक्चर की बुनियादी जानकारी
गो भाषा में, स्ट्रक्चर एक संयुक्त डेटा प्रकार है जो विभिन्न या समान प्रकार के डेटा को एक एकल इकाई में जोड़ता है। स्ट्रक्चर्स गो में महत्वपूर्ण स्थान रखते हैं क्योंकि वे पारंपरिक ऑब्जेक्ट-संवादात्मक प्रोग्रामिंग भाषाओं से हल्के अंतरों के साथ पीछे थोडा विभिन्न रूप से बनाए गए हैं।
स्ट्रक्चर की आवश्यकता निम्नलिखित पहलुओं से उत्पन्न होती है:
- संबंधित चीजों को एक साथ व्यवस्थित करके कोड की रखरखाव को बढ़ावा देने के लिए परिस्थितियों के साथ चर्चा करने
- "कक्षाओं" को अनुकरण करने का तरीका प्रदान करके "कक्षाओं" को अनुकरण और संग्रहीकरण सुविधाएं सुनिश्चित करने का माध्यम प्रदान करना।
- JSON, डेटाबेस रिकॉर्ड आदि जैसी डाटा संरचनाओं के साथ बातचीत करते समय, स्ट्रक्चर्स एक सुविधाजनक मैपिंग उपकरण प्रदान करते हैं।
स्ट्रक्चर के साथ डेटा को व्यवस्थित करने से असली दुनियावी वस्तु मॉडल्स का स्पष्ट प्रतिनिधित्व किया जा सकता है, जैसे उपयोगकर्ता, आदेश आदि।
2 स्ट्रक्चर की परिभाषा
स्ट्रक्चर की परिभाषा का सिंटेक्स निम्नलिखित है:
type StructName struct {
Field1 FieldType1
Field2 FieldType2
// ... अन्य सदस्य चर
}
-
type
कीवर्ड स्ट्रक्चर की परिभाषा को प्रस्तुत करता है। -
StructName
स्ट्रक्चर प्रकार का नाम है, जो गो की नामकरण अनुशासन का पालन करते हैं, आम तौर पर उसकी निर्यातिकता को सूचित करने के लिए मामूली किया जाता है। -
struct
कीवर्ड इसे इस स्ट्रक्चर प्रकार को सूचित करता है। - कुड़ा ब्रेसेज
{}
के भीतर, स्ट्रक्चर के सदस्य चर (फ़ील्ड) परिभाषित हैं, जिसके प्रत्येक के बाद उसके प्रकार होते हैं।
सदस्य चरों के प्रकार किसी भी प्रकार का हो सकता है, जिसमें मूल या अवयवीय प्रकार (जैसे int
, string
, आदि) और जटिल प्रकार (जैसे बेतरतीब प्रकार, स्लाइस, एक अन्य स्ट्रक्चर, आदि) शामिल हो सकता है।
उदाहरण के रूप में, एक व्यक्ति का प्रतिनिधित्व करते हुए स्ट्रक्चर की परिभाषा:
type Person struct {
Name string
Age int
Emails []string // जैसे स्लाइस जैसे जटिल प्रकार शामिल कर सकता है
}
उपरोक्त कोड में, Person
स्ट्रक्चर के तीन सदस्य चर हैं: Name
स्ट्रिंग प्रकार का, Age
पूर्णांक प्रकार का, और Emails
स्ट्रिंग स्लाइस प्रकार का, इससे सूचित होता है कि एक व्यक्ति के पास कई ईमेल पते हो सकते हैं।
3 स्ट्रक्चर उत्पन्न और प्रारंभीकरण
3.1 स्ट्रक्चर एक उदाहरण बनाना
स्ट्रक्चर का एक उदाहरण बनाने के दो तरीके होते हैं: सीधे घोषणा या new
कीवर्ड का उपयोग करके।
सीधी घोषणा:
var p Person
उपरोक्त कोड स्ट्रक्चर का p
एक उदाहरण बनाता है, जहां स्ट्रक्चर के प्रत्येक सदस्य चर का जो सदस्य चर है, वह उसके प्रत्येक प्रकार का शून्य मूल्य होता है।
new
कीवर्ड का उपयोग करके:
p := new(Person)
new
कीवर्ड का उपयोग करके स्ट्रक्चर बनाने से स्थिर्वरियता का पता नहीं चलती है। यहां चर p
प्रकार *Person
का होता है, जो एक नए नियत्रित प्रकार की नैली में संदर्भित होता है जहां सदस्य चरों को शून्य मूल्यों से प्रारंभ किया गया होता है।
3.2 स्ट्रक्चर उदाहरणों की प्रारंभीकरण
स्ट्रक्चर के उदाहरण को बनाते समय उन्हें एक साथ इनिशियलाइज़ किया जा सकता है, फ़ील्ड नामों के साथ या बिना फ़ील्ड नामों का उपयोग करके दो तरीकों से:
फ़ील्ड नामों के साथ इनिशियलाइज़ करना:
p := Person{
Name: "Alice",
Age: 30,
Emails: []string{"[email protected]", "[email protected]"},
}
जब फ़ील्ड नामों के साथ इनिशियलाइज़ करते हैं, इससे सूचित होता है कि इनिशियलाइज़ करने की क्रमबद्धता स्ट्रक्चर की परिभाषा के घोषित क्रम के समान होने की आवश्यकता नहीं है, और कोई अपरिणामित फ़ील्ड अपने शून्य मूल्यों को बनाए रखते हैं।
फ़ील्ड नामों के बिना इनिशियलाइज़ करना:
p := Person{"Bob", 25, []string{"[email protected]"}}
फ़ील्ड नामों के बिना इनिशियलाइज़ करते समय, सुनिश्चित करें कि प्रत्येक सदस्य चर के प्रारंभिक मूल्य स्ट्रक्चर की परिभाषा के अद्यतित क्रम के समान हो, और कोई फ़ील्ड छूटा नहीं हो सकता।
इसके अतिरिक्त, स्ट्रक्चर्स को विशेष फ़ील्डों के साथ प्रारंभ किया जा सकता है, और किसी भी अनिर्दिष्ट फ़ील्डों को शून्य मूल्यों को ले लेंगे:
p := Person{Name: "Charlie"}
इस उदाहरण में, केवल Name
फ़ील्ड को प्रारंभ किया गया है, जबकि Age
और Emails
दोनों अपने संबंधित शून्य मूल्यों को लेंगे।
4 स्ट्रक्चर सदस्यों का पहुँच
गो में स्ट्रक्चर के सदस्य चरों का पहुँच बहुत सीधा होता है, इसे डॉट (.
) ऑपरेटर का उपयोग करके प्राप्त किया जा सकता है। यदि आपके पास एक स्ट्रक्चर चर है, तो आप इस तरीके से उसके सदस्य मान को पढ़ सकते हैं या संशोधित कर सकते हैं।
// Define a simple struct
type Rectangle struct {
length, width float64
}
// Define a method for the Rectangle struct to calculate the area of the rectangle
func (r Rectangle) Area() float64 {
return r.length * r.width
}
उपरोक्त कोड में, विधि क्षेत्रफल
को संरेखण आयत
के साथ जोड़ा गया है। विधि की परिभाषा में, (r आयत)
अपराप्ता है, जो निर्धारित करता है कि यह विधि प्रकार आयत
से जुड़ी हुई है। प्राप्तकर्ता विधि नाम से पहले प्रकट होता है।
6.2 मान स्वीकरक और पॉइंटर स्वीकरक
विधियों को रिसीवर के प्रकार के आधार पर मान और पॉइंटर स्वीकरक में वर्गीकृत किया जा सकता है। मान स्वीकरक स्ट्रक्ट की एक प्रतिलिपि का उपयोग करके विधि को बुलाने के लिए करता है, जबकि पॉइंटर स्वीकरक स्ट्रक्ट के एक पॉइंटर का उपयोग करता है और मूल स्ट्रक्ट को संशोधित कर सकता है।
// मान स्वीकरक के साथ विधि को परिभाषित करें
func (r Rectangle) परिधि() float64 {
return 2 * (r.length + r.width)
}
// पॉइंटर स्वीकरक के साथ विधि को परिभाषित करें, जो स्ट्रक्ट को संशोधित कर सकती है
func (r *Rectangle) लंबाई_सेट(newLength float64) {
r.length = newLength // मूल स्ट्रक्ट को संशोधित कर सकता है
}
उपरोक्त उदाहरण में, परिधि
एक मान स्वीकरक विधि है, इसे बुलाने से Rectangle
के मान में परिवर्तन नहीं होगा। हालांकि, लंबाई_सेट
एक पॉइंटर स्वीकरक विधि है, और इस विधि को बुलाने से मूल Rectangle
उदाहरण पर प्रभाव पड़ेगा।
6.3 विधि आवहन
आप स्ट्रक्ट की विधियों को स्ट्रक्ट चरण और इसके पॉइंटर का उपयोग करके बुला सकते हैं।
func main() {
rect := Rectangle{length: 10, width: 5}
// मान स्वीकरक के साथ विधि को बुलाएं
fmt.Println("क्षेत्रफल:", rect.Area())
// मान स्वीकरक के साथ विधि को बुलाएं
fmt.Println("परिधि:", rect.Perimeter())
// पॉइंटर स्वीकरक के साथ विधि को बुलाएं
rect.SetLength(20)
// फिर से मान स्वीकरक के साथ विधि को बुलाएं, ध्यान दें कि लंबाई को संशोधित किया गया है
fmt.Println("संशोधन के बाद, क्षेत्रफल:", rect.Area())
}
जब आप स्ट्रक्ट का पॉइंटर उपयोग करके एक विधि को बुलाते हैं, तो Go स्वचालित रूप से मान और पॉइंटर के बीच परिवर्तन का नियंत्रण करता है, चाहे आपकी विधि मान स्वीकरक के साथ परिभाषित की गई हो या पॉइंटर स्वीकरक के साथ।
6.4 रिसीवर प्रकार चयन
विधियों को परिभाषित करते समय, आपको स्थिति के आधार पर मान स्वीकरक या पॉइंटर स्वीकरक का उपयोग करना चाहिए, इसके आधार पर निर्णय लेना चाहिए। यहां कुछ सामान्य मार्गदर्शिकाएँ हैं:
- यदि विधि को स्ट्रक्चर की सामग्री में परिवर्तन करने की आवश्यकता होती है, तो पॉइंटर स्वीकरक का उपयोग करें।
- यदि संरचना बड़ी है और प्रतिलिपि करने का खर्च अधिक है, तो पॉइंटर स्वीकरक का उपयोग करें।
- यदि आप चाहते हैं कि विधि मूल स्वीकरक द्वारा देखे गए मान को संशोधित करे, तो पॉइंटर स्वीकरक का उपयोग करें।
- कुशलतान के लिए, यदि आप संरचना सामग्री को संशोधित नहीं भी करते हैं, तो बड़ी संरचना के लिए पॉइंटर स्वीकरक का उपयोग करना सार्थक है।
- छोटी संरचनाओं के लिए, या केवल संशोधन के बिना डेटा पढ़ने की आवश्यकता हो, जस्ता स्वीकरक अक्सर सरल और अधिक कुशल होता है।
स्ट्रक्ट विध
8.1 स्ट्रक्ट की तुलना
Go में, स्ट्रक्ट के दो इंस्टेंस की सीधी तुलना की अनुमति है, लेकिन यह तुलना स्ट्रक्ट की फ़ील्ड के मानों पर आधारित होती है। यदि सभी फ़ील्ड मान समान हैं, तो दो स्ट्रक्ट के इंस्टेंस को समान माना जाता है। ध्यान देना चाहिए कि सभी फ़ील्ड प्रकारों की तुलना नहीं की जा सकती है। उदाहरण के लिए, स्लाइस वाला एक स्ट्रक्ट सीधी तुलना नहीं की जा सकती है।
नीचे एक स्ट्रक्ट की तुलना का उदाहरण है:
package main
import "fmt"
type Point struct {
X, Y int
}
func main() {
p1 := Point{1, 2}
p2 := Point{1, 2}
p3 := Point{1, 3}
fmt.Println("p1 == p2:", p1 == p2) // आउटपुट: p1 == p2: true
fmt.Println("p1 == p3:", p1 == p3) // आउटपुट: p1 == p3: false
}
इस उदाहरण में, p1
और p2
समान माने जाते हैं क्योंकि उनके सभी फ़ील्ड मान समान हैं। और p3
p1
के समान नहीं है क्योंकि Y
का मान अलग है।
8.2 स्ट्रक्ट की कॉपी
Go में, स्ट्रक्ट के इंस्टेंस को विस्तार से कॉपी किया जा सकता है। यह कॉपी गहरी कॉपी या शैलो कॉपी दोनों हो सकती है, जो कि स्ट्रक्ट के फ़ील्ड के प्रकार पर निर्भर करता है।
अगर स्ट्रक्ट में केवल मूलभूत प्रकार (जैसे int
, string
, आदि) होते हैं, तो कॉपी गहरी कॉपी होती है। अगर स्ट्रक्ट में संदर्भ प्रकार (जैसे स्लाइस, मैप, आदि) होते हैं, तो कॉपी शैलो होगी, और मूल इंस्टेंस और नई कॉपी इंस्टेंस संदर्भ प्रकार की संग्रहीत स्मृति का साझा करेंगे।
नीचे एक स्ट्रक्ट की कॉपी का एक उदाहरण है:
package main
import "fmt"
type Data struct {
Numbers []int
}
func main() {
// Data स्ट्रक्ट के एक इंस्टेंस को आरंभ करें
original := Data{Numbers: []int{1, 2, 3}}
// स्ट्रक्ट की कॉपी करें
copied := original
// कॉपी किए गए स्लाइस के तत्वों को संशोधित करें
copied.Numbers[0] = 100
// मूल और कॉपी इंस्टेंस के तत्वों को देखें
fmt.Println("Original:", original.Numbers) // आउटपुट: Original: [100 2 3]
fmt.Println("Copied:", copied.Numbers) // आउटपुट: Copied: [100 2 3]
}
जैसा कि उदाहरण में दिखाया गया है, original
और copied
इंस्टेंस समान स्लाइस का साझा करते हैं, इसलिए copied
में स्लाइस डेटा को संशोधित करने से original
में भी स्लाइस डेटा पर प्रभाव पड़ेगा।
इस समस्या से बचने के लिए, आप स्पष्ट रूप से स्लाइस तत्वों को एक नई स्लाइस में कॉपी करके सच्ची गहरी कॉपी प्राप्त कर सकते हैं:
newNumbers := make([]int, len(original.Numbers))
copy(newNumbers, original.Numbers)
copied := Data{Numbers: newNumbers}
इस तरह से, copied
में किसी भी संशोधन से original
पर कोई प्रभाव नहीं पड़ेगा।