رفتن به محتوای اصلی
  1. وبلاگ/

رفتارهای عجیب تابع append در golang

·2 دقیقه· loading · loading · · ·
Tip Golang Slice Memory
محمدمعین عربی
نویسنده
محمدمعین عربی
بیو من
فهرست مطالب

مقدمه
#

همیشه یاد گرفتن یه زبون جدید چالش‌های خاصی داره. یادم میاد زمانی که شروع کرده بودم شی گرایی پایتون رو یاد می‌گرفتم و با جاوا مقایسش می‌کردم، همه چیزش خیلی عجیب بود. الان هم که دارم go رو یاد می‌گیرم یه چیزاییش عجیبه ولی می‌دونم زمان بگذره همه این‌ها عادی و بدیهی میشه.

در این مطلب هم می‌خوام در مورد تابع append بنویسم.

تصور اشتباه از این تابع
#

همونطور که می‌دونید این تابع یک slice به همراه داده‌های جدیدی که قراره به اسلایس اضافه بشن رو ورودی می‌گیره و بعد یک اسلایس جدید بر می‌گردونه.

ولی دقیقا تصور اشتباه من همین جا بود: اسلایس جدید!

من همیشه سعی می‌کنم توابع و کلاس‌هایی که در هر زبونی استفاده می‌کنم رو خوب بشناسم. بدونم اون پشتش چه اتفاقی داره می‌افته؛ صرفا یه مصرف‌کننده نباشم. به خاطر همین سعی کردم اتفاقی که پشت این تابع در حال رخ دادن هست رو با زبون c++ تصور کنم. می‌گفتم خب اگر قرار بود این رو توی c++ پیاده‌سازی کنم، باید اول یه حافظه جدید با یه سایز اضافه‌تر می‌ساختم (new)، بعد تمام المنت‌های آرایه قبلی رو کپی می‌کردم و در آخر حافظه قبلی رو delete می‌کردم.

ولی اشتباه من همین جا بود که فکر می‌کردم capacity همزمان با length یه دونه یه دونه زیاد میشه. ولی در واقع capacity جلوتر حرکت میکنه و احتمالا 1.5 برابر میشه. خب در چنین حالتی سر آدم که درد نمی‌کنه که اگر capacity کافی برای اضافه کردن المنت جدید وجود داره بیاد کلا یه آرایه جدید بسازه و همه‌ی اون المنت‌های قبلی رو هم کپی کنه.

کد
#

مثلا کد زیر همین اتفاق رو خیلی جالب داره نشون میده:

package main

import "fmt"

func main() {
    s := make([]int, 0, 5)
    s = append(s, []int{1, 2, 3, 4}...)

    a := append(s, 5)
    fmt.Println(a)

    b := append(s, 6)
    fmt.Println(b)
    fmt.Println(a)
}

خروجی:

[1 2 3 4 5]
[1 2 3 4 6]
[1 2 3 4 6]

اگر همین s سایزش 4 بود به جای 5 خروجی این میشد:

[1 2 3 4 5]
[1 2 3 4 6]
[1 2 3 4 5]

پس همیشه از اسلایس قبلی کپی گرفته نمیشه و یه اسلایس جدید ساخته بشه.

مقاله‌های مرتبط

تاثیر Allocate و Deallocate کردن‌های بیهوده بر زمان اجرایی
·3 دقیقه· loading · loading
Tip Leetcode Algorithm Golang Optimization Memory
چگونه یک متن Markdown بنویسیم؟
·2 دقیقه· loading · loading
Educational Markdown
چرا git pull خوب نیست؟!
·2 دقیقه· loading · loading
Tip Git Github