البُنية أو بالانكليزي Struct هو نوع بيانات Datatype مخصص من اختراع المستخدم (المبرمج) used-defined, حيث يحوي مجموعة من الحقول (تُدعى الخصائص Properties).
وتُستخدم البُنى لتجميع البيانات المتشابهة لتشكل وحدة مفردة مستقلة.
وأي شيئ من العالم الواقعي يكون له مجموعة الخصائص, يمكن أن يتم تمثيله ببنية struct, فمثلاً “الأشخاص”, “الموظفون”, “الكتب”, “النباتات”, “الموبايلات”, “العطورات” و…. الخ.
– إنشاء بُنية Struct
من خلال المثال التالي سننشئ بنية Person حيث ستملك بعض الخصائص مثل الاسم الاول والكنية والعمر.
مثال
type Person struct {
FirstName string
LastName string
Age int
}
الكلمة المفتاحية type يمكننا من خلالها انشاء نوع بيانات جديد في لغة غو, ثم يتبعها تسمية النوع الذي نريد انشاؤه (في هذه الحالة Person) والكلمة المفتاحية struct هي للاشارة اننا نريد انشاء بنية Structure (يوجد غيرها مثل الواجهات interface)
والبنية تحتوي مجموعة من الحقول داخل قوسين {}, ونسمي هذه الحقول بالخصائص Properties التي تصِف البنية, ولكل خاصية منها “تسمية” ونوع بيانات, فمثلاً خاصية الاسم الأول اسمها FirstName ونوع بياناتها هو string.
وباعتبار أن أول خاصيتين ( الاسم الأول و الكنية) لهما نفس نوع البيانات string فيمكننا تقصير الكود عبر كتابتهما بنفس السطر كالاتي
type Person struct {
FirstName, LastName string
Age int
}
– الاعلان عن بنية واسناد قيم أولية لها
مثل أي نوع بيانات آخر, يمكننا الاعلان عن متغير يحمل نوع بيانات البنية كالاتي
// Declares a variable of type 'Person'
var fadi Person
الكود السابق ينشئ متغير من نوع Person, وبما أننا لم نحدد خصائصه فستأخذ تلقائياً القيمة الصفرية, فمثلاً الخصائص من نوع string ستكون قيمتها فارغة, والقيم من نوع int ستكون قيمتها صفر .
– اسناد القيم الأولية للبنية
يوجد طريقتان لاسناد القيم الأولية لأي بنية كانت, الطريقة الأولى تكون كالاتي
// Initialize a struct by supplying the value of all the struct fields.
var p = Person{"Firas", "Darwish", 25}
في هذه الطريقة يجب إدخال قيم خصائص البنية حسب الترتيب الأصلي للخصائص عندما تم الاعلان عنها في عبارة type Person struct
وأيضاً يجب الملاحظة أنه لايمكن اسناد قيم لبعض الخصائص وترك بعضها الآخر, بل يجب إسناد قيم لجميع الخصائص وإلا سيظهر خطأ شبيه بالاتي
Compiler Error: too few values in struct initializer
والطريقة الثانية لاسناد القيم الأولية للبنية هي عبر ذكر اسم الخاصية وقيمتها (في الطريقة الاولى نذكر القيمة فقط دون اسم الخاصية)
مثال
var p = Person{FirstName: "Firas", LastName: "Darwish", Age: 25}
ويمكن وضع كل خاصية بسطر بشرط وضع فاصلة عشرية بنهاية كل الاسطر كالاتي
var p = Person{
FirstName: "Firas",
LastName: "Darwish",
Age: 25,
}
وعند استخدام الطريقة الثانية, يمكننا إسناد قيم لبعض الخصائص وترك بعضها الآخر
var p = Person{FirstName: "Firas"}
وحتى الان يكون شكل البرنامج كالاتي
package main
import (
"fmt"
)
// Defining a struct type
type Person struct {
FirstName string
LastName string
Age int
}
func main() {
// Declaring a variable of a `struct` type
var p Person
fmt.Println(p)
// Declaring and initializing a struct using a struct literal
p1 := Person{"Firas", "Darwish", 25}
fmt.Println("Person1: ", p1)
// Naming fields while initializing a struct
p2 := Person{
FirstName: "John",
LastName: "Snow",
Age: 45,
}
fmt.Println("Person2: ", p2)
// Uninitialized fields are set to their corresponding zero-value
p3 := Person{FirstName: "Robert"}
fmt.Println("Person3: ", p3)
}
ونتيجة تنفيذ البرنامج تكون كالاتي
{ 0}
Person1: {Firas Darwish 25}
Person2: {John Snow 45}
Person3: {Robert 0}
– التعامل مع خصائص (حقول) البُنية
يمكننا إظهار قيم الخصائص أو التعديل عليها عبر استخدام معامل النقطة ( . )
مثال
package main
import (
"fmt"
)
type Car struct {
Name, Model, Color string
WeightInKg float64
}
func main() {
c := Car{
Name: "Ferrari",
Model: "GTC4",
Color: "Red",
WeightInKg: 1920,
}
// Accessing struct fields using the dot operator
fmt.Println("Car Name: ", c.Name)
fmt.Println("Car Color: ", c.Color)
// Assigning a new value to a struct field
c.Color = "Black"
fmt.Println("Car: ", c)
}
والنتيجة تكون
Car Name: Ferrari
Car Color: Red
Car: {Ferrari GTC4 Black 1920}
– انشاء متغير من بنية عبر دالة new
يمكننا استخدام الدالة new التي توفرها لغة غو لكي ننشئ متغير من بنية معينة, ويمكن اعتبارها طريقة ثالثة لانشاء متغير من بنية.
مثال
package main
import "fmt"
type Employee struct {
Id int
Name string
}
func main() {
// You can also get a pointer to a struct using the built-in new() function
// It allocates enough memory to fit a value of the given struct type, and returns a pointer to it
pEmp := new(Employee)
pEmp.Id = 1000
pEmp.Name = "Sachin"
fmt.Println(pEmp)
}
والنتيجة
&{1000 Sachin}