برش در GO: شیرجه عمیق با مثال

هنگام نوشتن برنامه های GO ، متوجه خواهید شد که آرایه ها اغلب برای عملی بودن بسیار سفت و سخت هستند. این جایی است که برش بیا بازی برش ها انتزاع داخلی GO بر روی آرایه هایی هستند که انعطاف پذیری ، قدرت و عملکرد را ارائه می دهند.
در این وبلاگ ، ما بررسی خواهیم کرد:
- چه برش هایی هستند
- چگونه آنها در داخل کار می کنند
- نحوه ایجاد و استفاده از آنها
- مشکلات مشترک
- بهترین شیوه ها با مثال
📌 برش چیست؟
بوها برش یک دیدگاه پویا و انعطاف پذیر به عناصر یک آرایه است. این خود داده ها را ذخیره نمی کند – به یک آرایه اساسی اشاره می کند.
ساختار برش (داخلی)
یک برش در GO یک ساختار کوچک با 3 زمینه است:
type slice struct {
ptr *T // pointer to the underlying array
len int // number of elements in the slice
cap int // total capacity (from ptr to end of array)
}
✅ ایجاد برش
1. از یک آرایه
arr := [5]int{10, 20, 30, 40, 50}
slice := arr[1:4] // [20 30 40]
در اینجا:
-
slice
آرایه را ارجاع می دهدarr
از فهرست1
به3
(به استثنای فهرست4
). -
len(slice)
= 3 -
cap(slice)
= 4 (از فهرست 1 تا انتهای آرایه)
2. با استفاده از slice literal
numbers := []int{1, 2, 3}
این هم یک برش و هم آرایه زیرین آن ایجاد می کند.
3. استفاده از make()
s := make([]int, 3) // [0 0 0]
s := make([]int, 3, 5) // len=3, cap=5
🔁 برش یک برش
data := []int{100, 200, 300, 400}
sub := data[1:3] // [200 300]
این زیر شکاف حافظه را با برش اصلی به اشتراک می گذارد. متغیر sub
تأثیر دادن data
:
sub[0] = 999
fmt.Println(data) // [100 999 300 400]
➕ ضمیمه عناصر
nums := []int{1, 2}
nums = append(nums, 3, 4) // [1 2 3 4]
اگر ظرفیت برش پر است ، به طور خودکار یک آرایه زیرین جدید را اختصاص دهید.
⚠ رفتار حافظه مشترک
arr := []int{1, 2, 3, 4}
s1 := arr[0:2] // [1 2]
s2 := arr[1:3] // [2 3]
s1[1] = 999
fmt.Println(arr) // [1 999 3 4]
fmt.Println(s2) // [999 3]
نکته:
برای جلوگیری از این ، استفاده کنید copy()
:
original := []int{1, 2, 3}
clone := make([]int, len(original))
copy(clone, original)
📈 رشد ظرفیت با append()
به طور معمول بروید ظرفیت را دو برابر می کند هنگامی که ضمیمه بیش از ظرفیت فعلی است.
s := make([]int, 0, 2)
s = append(s, 1, 2, 3)
fmt.Println(s) // [1 2 3]
اگر ظرفیت بیش از حد باشد ، آرایه جدیدی در پشت صحنه اختصاص می یابد.
📦 توابع داخلی
عمل | شرح |
---|---|
len(slice) |
تعداد عناصر را برمی گرداند |
cap(slice) |
ظرفیت کل را باز می گرداند |
append(slice, elems...) |
عناصر را ضمیمه می کند |
copy(dst, src) |
عناصر را کپی می کند |
🧪 مثال کامل
func main() {
original := []int{10, 20, 30, 40, 50}
slice1 := original[1:4]
fmt.Println("Slice1:", slice1) // [20 30 40]
slice2 := append(slice1, 99)
fmt.Println("Original:", original)
fmt.Println("Slice2:", slice2)
slice1[0] = 777
fmt.Println("Modified Slice1:", slice1)
fmt.Println("Modified Original:", original)
}
خروجی (ممکن است بر اساس استفاده مجدد از ظرفیت متفاوت باشد):
Slice1: [20 30 40]
Original: [10 20 30 40 99]
Slice2: [20 30 40 99]
Modified Slice1: [777 30 40]
Modified Original: [10 777 30 40 99]
❗ اشتباهات رایج
🔹 فرضیه برش ها مستقل هستند:
a := []int{1, 2, 3}
b := a
b[0] = 999
fmt.Println(a) // [999 2 3]
استفاده کردن copy()
برای کلون کردن یک قطعه.
🔹 فراموش کردن آن append()
ممکن است آرایه جدیدی ایجاد کند
همیشه بررسی کنید که آیا برش شما هنوز به حافظه اصلی اشاره می کند اگر به رفتار مشترک متکی هستید.
✅ بهترین روشها
- برای اکثر مجموعه ها از برش ها استفاده کنید – آنها از آرایه ها اصطلاحات و پویاتر هستند.
- استفاده کردن
copy()
وقتی استقلال لازم است. - از برش های غیر ضروری در حلقه های بحرانی عملکرد خودداری کنید.
- استفاده کردن
make([]T, len, cap)
اگر اندازه قبل از زمان را می دانید.
🧠 خلاصه
نشان | مجموعه | برش |
---|---|---|
اندازه | ثابت | پویا |
به اشتراک گذاری حافظه | بله | بله |
پشتیبانی ضمیمه | هیچ | بله |
استفاده ترجیحی | ناچیز | همیشه |
thoughts افکار نهایی
برش ها سنگ بنای طراحی GO است و عملکرد را با انعطاف پذیری ترکیب می کند. درک چگونگی به اشتراک گذاشتن برش حافظه با آرایه ها ، رشد و تعامل با توابع داخلی برای نوشتن کد GO ایدیوماتیک و ایمن ضروری است.
پس از تسلط بر برش ، برنامه های تمیزتر و کارآمدتری می نویسید – و از برخی از اشکالات پیچیده جلوگیری می کنید!