खोज…
परिचय
संरचनाएं एक साथ पैक किए गए विभिन्न चर के सेट हैं। संरचना ही केवल एक पैकेज है जिसमें चर होते हैं और उन्हें आसानी से सुलभ बनाया जाता है।
सी के विपरीत, गो के ढांचे में उनसे जुड़े तरीके हो सकते हैं। यह उन्हें इंटरफेस लागू करने की भी अनुमति देता है। यह गो की वस्तुओं को वस्तुओं के समान बनाता है, लेकिन वे विरासत के रूप में वस्तु उन्मुख भाषाओं में ज्ञात कुछ प्रमुख विशेषताओं को याद कर रहे हैं (शायद जानबूझकर)।
मूल घोषणा
एक बुनियादी संरचना इस प्रकार घोषित की गई है:
type User struct {
FirstName, LastName string
Email string
Age int
}
प्रत्येक मान को एक फ़ील्ड कहा जाता है। फ़ील्ड को आमतौर पर एक पंक्ति में लिखा जाता है, जिसमें फ़ील्ड का नाम उसके प्रकार से पहले होता है। ऊपर दिए गए उदाहरण में FirstName
और LastName
रूप में एक ही प्रकार के लगातार क्षेत्रों को जोड़ा जा सकता है।
निर्यात बनाम निर्यातित क्षेत्र (निजी बनाम सार्वजनिक)
संरचना क्षेत्र जिनके नाम एक बड़े अक्षर से शुरू होते हैं, निर्यात किए जाते हैं। अन्य सभी नाम अस्पष्टीकृत हैं।
type Account struct {
UserID int // exported
accessToken string // unexported
}
अनएक्सपोर्ट किए गए फ़ील्ड को केवल उसी पैकेज के भीतर कोड द्वारा एक्सेस किया जा सकता है। जैसे, यदि आप कभी किसी अलग पैकेज से किसी क्षेत्र तक पहुँच बना रहे हैं, तो इसके नाम को अपरकेस अक्षर से शुरू करना होगा।
package main
import "bank"
func main() {
var x = &bank.Account{
UserID: 1, // this works fine
accessToken: "one", // this does not work, since accessToken is unexported
}
}
हालाँकि, bank
पैकेज के भीतर, आप UserId और accessToken दोनों को बिना किसी समस्या के एक्सेस कर सकते हैं।
पैकेज bank
को इस तरह लागू किया जा सकता है:
package bank
type Account struct {
UserID int
accessToken string
}
func ProcessUser(u *Account) {
u.accessToken = doSomething(u) // ProcessUser() can access u.accessToken because
// it's defined in the same package
}
रचना और एंबेडिंग
रचना विरासत का एक विकल्प प्रदान करती है। एक घोषणा में एक अन्य प्रकार का नाम शामिल हो सकता है:
type Request struct {
Resource string
}
type AuthenticatedRequest struct {
Request
Username, Password string
}
ऊपर दिए गए उदाहरण में, AuthenticatedRequest
में चार सार्वजनिक सदस्य होंगे: Resource
, Request
, Username
और Password
।
कंपोजिट संरचना को तत्काल बनाया जा सकता है और सामान्य संरचना की तरह उपयोग किया जाता है:
func main() {
ar := new(AuthenticatedRequest)
ar.Resource = "example.com/request"
ar.Username = "bob"
ar.Password = "P@ssw0rd"
fmt.Printf("%#v", ar)
}
एम्बेडिंग
पिछले उदाहरण में, Request
एक एम्बेडेड फ़ील्ड है। एक अलग प्रकार एम्बेड करके भी संरचना प्राप्त की जा सकती है। यह उपयोगी है, उदाहरण के लिए, अधिक कार्यक्षमता के साथ एक संरचना को सजाने के लिए। उदाहरण के लिए, संसाधन उदाहरण के साथ जारी रखते हुए, हम एक ऐसा फ़ंक्शन चाहते हैं जो संसाधन फ़ील्ड की सामग्री को http://
या https://
साथ उपसर्ग करता है। हमारे पास दो विकल्प हैं: AuthenticatedRequest पर नए तरीके बनाएं या इसे एक अलग संरचना से एम्बेड करें :
type ResourceFormatter struct {}
func(r *ResourceFormatter) FormatHTTP(resource string) string {
return fmt.Sprintf("http://%s", resource)
}
func(r *ResourceFormatter) FormatHTTPS(resource string) string {
return fmt.Sprintf("https://%s", resource)
}
type AuthenticatedRequest struct {
Request
Username, Password string
ResourceFormatter
}
और अब मुख्य कार्य निम्नलिखित कर सकते हैं:
func main() {
ar := new(AuthenticatedRequest)
ar.Resource = "www.example.com/request"
ar.Username = "bob"
ar.Password = "P@ssw0rd"
println(ar.FormatHTTP(ar.Resource))
println(ar.FormatHTTPS(ar.Resource))
fmt.Printf("%#v", ar)
}
यह देखें कि AuthenticatedRequest
पास एक ResourceFormatter
एम्बेडेड संरचना है।
लेकिन इसका नकारात्मक पक्ष यह है कि आप अपनी रचना के बाहर वस्तुओं तक नहीं पहुँच सकते। इसलिए ResourceFormatter
सदस्यों को AuthenticatedRequest
से एक्सेस नहीं कर सकता है।
तरीके
संरचना के तरीके बहुत ही समान हैं:
type User struct {
name string
}
func (u User) Name() string {
return u.name
}
func (u *User) SetName(newName string) {
u.name = newName
}
एकमात्र अंतर विधि रिसीवर के अतिरिक्त है। इसे या तो टाइप के उदाहरण के रूप में या पॉइंटर के उदाहरण के रूप में घोषित किया जा सकता है। चूंकि SetName()
उदाहरण को उत्परिवर्तित करता है, उदाहरण में स्थायी परिवर्तन को प्रभावित करने के लिए रिसीवर को एक सूचक होना चाहिए।
उदाहरण के लिए:
package main
import "fmt"
type User struct {
name string
}
func (u User) Name() string {
return u.name
}
func (u *User) SetName(newName string) {
u.name = newName
}
func main() {
var me User
me.SetName("Slim Shady")
fmt.Println("My name is", me.Name())
}
अनाम संरचना
अनाम संरचना बनाना संभव है:
data := struct {
Number int
Text string
} {
42,
"Hello world!",
}
पूर्ण उदाहरण:
package main
import (
"fmt"
)
func main() {
data := struct {Number int; Text string}{42, "Hello world!"} // anonymous struct
fmt.Printf("%+v\n", data)
}
टैग
संरचना क्षेत्रों में उनसे जुड़े टैग हो सकते हैं। डेवलपर द्वारा किसी फ़ील्ड के बारे में निर्दिष्ट कस्टम जानकारी प्राप्त करने के लिए ये टैग reflect
पैकेज द्वारा पढ़े जा सकते हैं।
struct Account {
Username string `json:"username"`
DisplayName string `json:"display_name"`
FavoriteColor string `json:"favorite_color,omitempty"`
}
उपरोक्त उदाहरण में, टैग्स का उपयोग encoding/json
पैकेज द्वारा उपयोग किए जाने वाले प्रमुख नामों को बदलने के लिए किया जाता है, जब JSON को मार्श या अनमर्श किया जाता है।
हालांकि टैग किसी भी स्ट्रिंग मान हो सकता है, यह अंतरिक्ष अलग key:"value"
का उपयोग करने के लिए सबसे अच्छा अभ्यास माना जाता है key:"value"
जोड़े:
struct StructName {
FieldName int `package1:"customdata,moredata" package2:"info"`
}
encoding/xml
और encoding/json
पैकेज के साथ उपयोग किए जाने वाले संरचनात्मक टैग पूरे मानक लिबरी में उपयोग किए जाते हैं।
संरचनात्मक प्रतियाँ बनाना।
एक संरचना को असाइनमेंट का उपयोग करके कॉपी किया जा सकता है।
type T struct {
I int
S string
}
// initialize a struct
t := T{1, "one"}
// make struct copy
u := t // u has its field values equal to t
if u == t { // true
fmt.Println("u and t are equal") // Prints: "u and t are equal"
}
उपरोक्त मामले में, 't'
और 'u' अब अलग-अलग ऑब्जेक्ट्स (संरचनात्मक मूल्य) हैं।
चूँकि T
में कोई संदर्भ प्रकार (स्लाइस, मैप, चैनल) नहीं है, क्योंकि इसके क्षेत्र, t
और u
को एक दूसरे को प्रभावित किए बिना संशोधित किया जा सकता है।
fmt.Printf("t.I = %d, u.I = %d\n", t.I, u.I) // t.I = 100, u.I = 1
हालाँकि, यदि T
में एक संदर्भ प्रकार है, उदाहरण के लिए:
type T struct {
I int
S string
xs []int // a slice is a reference type
}
फिर असाइनमेंट के द्वारा एक साधारण कॉपी स्लाइस टाइप फ़ील्ड के मान के साथ-साथ नई ऑब्जेक्ट पर भी कॉपी होगी। यह दो अलग-अलग वस्तुओं में एक ही स्लाइस ऑब्जेक्ट का जिक्र करता है।
// initialize a struct
t := T{I: 1, S: "one", xs: []int{1, 2, 3}}
// make struct copy
u := t // u has its field values equal to t
चूँकि u और t दोनों अपने क्षेत्र xs के माध्यम से एक ही स्लाइस को संदर्भित करते हैं, एक वस्तु के स्लाइस में एक वैल्यू को अपडेट करते हुए दूसरे में परिवर्तन को दर्शाते हैं।
// update a slice field in u
u.xs[1] = 500
fmt.Printf("t.xs = %d, u.xs = %d\n", t.xs, u.xs)
// t.xs = [1 500 3], u.xs = [1 500 3]
इसलिए, यह सुनिश्चित करने के लिए अतिरिक्त ध्यान रखा जाना चाहिए कि यह संदर्भ प्रकार संपत्ति अनपेक्षित व्यवहार का उत्पादन न करे।
उदाहरण के लिए ऊपर की वस्तुओं को कॉपी करने के लिए, स्लाइस फ़ील्ड की एक स्पष्ट प्रति प्रदर्शित की जा सकती है:
// explicitly initialize u's slice field
u.xs = make([]int, len(t.xs))
// copy the slice values over from t
copy(u.xs, t.xs)
// updating slice value in u will not affect t
u.xs[1] = 500
fmt.Printf("t.xs = %d, u.xs = %d\n", t.xs, u.xs)
// t.xs = [1 2 3], u.xs = [1 500 3]
संरचना साहित्य
एक संरचनात्मक प्रकार का एक मूल्य एक संरचनात्मक शाब्दिक का उपयोग करके लिखा जा सकता है जो अपने क्षेत्रों के लिए मूल्यों को निर्दिष्ट करता है।
type Point struct { X, Y int }
p := Point{1, 2}
उपरोक्त उदाहरण सही क्रम में हर क्षेत्र को निर्दिष्ट करता है। जो उपयोगी नहीं है, क्योंकि प्रोग्रामर को सटीक फ़ील्ड्स को क्रम में याद रखना होगा। अधिक बार, कुछ या सभी फ़ील्ड नामों और उनके संबंधित मूल्यों को सूचीबद्ध करके एक संरचना को आरंभ किया जा सकता है।
anim := gif.GIF{LoopCount: nframes}
इसके प्रकारों के लिए शून्य फ़ील्ड को शून्य मान पर सेट किया गया है।
नोट: दो रूपों को एक ही शाब्दिक में नहीं मिलाया जा सकता है।
खाली ढांचा
एक संरचना नामांकित तत्वों का एक क्रम है, जिसे फ़ील्ड कहा जाता है, जिनमें से प्रत्येक का एक नाम और एक प्रकार है। खाली संरचना का कोई क्षेत्र नहीं है, इस अनाम खाली संरचना की तरह:
var s struct{}
या इस तरह नामित खाली संरचना प्रकार:
type T struct{}
खाली संरचना के बारे में दिलचस्प बात यह है कि, इसका आकार शून्य है ( Go Playground का प्रयास करें):
fmt.Println(unsafe.Sizeof(s))
यह 0
प्रिंट करता है, इसलिए खाली संरचना स्वयं कोई मेमोरी नहीं लेती है। इसलिए यह चैनल छोड़ने के लिए अच्छा विकल्प है, जैसे ( द प्ले प्लेग्राउंड आज़माएं):
package main
import (
"fmt"
"time"
)
func main() {
done := make(chan struct{})
go func() {
time.Sleep(1 * time.Second)
close(done)
}()
fmt.Println("Wait...")
<-done
fmt.Println("done.")
}