سرمایه گذاری متفاوت در سال نو 🍎🌱 ۳۵٪ تخفیف نوروزی ➕ حضور رایگان در مسترمایند نخبگان صنعت نرم‌افزار 💻✅
۰ ثانیه
۰ دقیقه
۰ ساعت
۱ دانشجوی سون‌لرن
ابهام در قسمتی از کد
جامعه گولنگ ایجاد شده در ۰۶ مرداد ۱۴۰۲

سلام

در قطعه کد زیر

func GetResponse(content chan<- string, url string) {
	// if url == "https://livescore-api.varzesh3.com/v1.0/livescore/today" {
	// 	time.Sleep(time.Millisecond * 50)
	// }
	// time.Sleep(time.Second * 3)
	client := http.Client{}
	request, err := http.NewRequest("GET", url, nil)
	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, time.Millisecond*10000)
	defer cancel()
	request = request.WithContext(ctx)
	if err != nil {
		panic(err)
	}
	request.Header = http.Header{}
	request.Header.Add("referer", "https://www.varzesh3.com/")
	response, err := client.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	responseBody, err := ioutil.ReadAll(response.Body)
	if err != nil {
		panic(err)
	}
	destination := &bytes.Buffer{}
	if err = json.Indent(destination, responseBody, "", "  "); err != nil {
		panic(err)
	}
	PrintlnWithTime("Before set content")
	content <- destination.String()
	PrintlnWithTime("After set content")
}

چرا از کد زیر استفاده شده است و کاربرد آن چیست؟ و همچنین در چه مواردی باید به این روش عمل نمود ؟

destination := &bytes.Buffer{}

سلام

چرا از کد زیر استفاده شده است؟

ورودی تابع Indent از نوع bytes.Buffer می‌باشد بنابراین ما باید همین نوع را پاس دهیم و هیچ راه دیگه ای نداریم.

کاربرد آن چیست؟ و همچنین در چه مواردی باید به این روش عمل نمود ؟

برای رسیدن به کاربرد از یک bad practice شروع می‌کنیم.

یکی از انواع داده ای که در اکثر زبان‌های برنامه نویسی وجود دارد و در استفاده از آن باید دقت داشته باشیم نوع string است.

قطعه کد زیر را در نظر بگیرید:

    var query string = "select "
    query += "name, family "
    query += "from "
    query += "users "
    query += "where 1 = 1 "
    query += "and name = `ali` "
    db.Execute(query)

زمانی که نیاز داریم تا مقدار یک رشته را تغییر دهیم نوشتن به این روش اشتباه می‌باشد. دلیل آن در این نهفته است که هر دفعه که شما این رشته را تغییر می‌دهید فارغ از متغیر پیشین یک فضای جدید در حافظه برای آن رزرو می‌شود. بنابراین این قطعه کد memory efficient نیست.

در بسیاری از زبان‌ها برای چنین مسایلی از string builder استفاده می‌شود. در گو هم string builder را داریم و هم bytes.Buffer.

این ساختارها از byte slice در پشت صحنه استفاده می‌کنند و تغییرات را روی آرایه داخلی اعمال میکنند. در نتیجه نیاز به رزرو فضاهای زیاد ندارند و memory efficient‌تر خواهند بود.

strings.Builder :

    var sbQuery strings.Builder
    sbQuery.WriteString("select ")
    sbQuery.WriteString("name, family ")
    sbQuery.WriteString("from ")
    sbQuery.WriteString("users ")
    sbQuery.WriteString("where 1 = 1 ")
    sbQuery.WriteString("and name = `ali` ")
    db.Execute(query)

bytes.Buffer :

    var btQuery bytes.Buffer = bytes.Buffer{}
    btQuery.WriteString("select ")
    btQuery.WriteString("name, family ")
    btQuery.WriteString("from ")
    btQuery.WriteString("users ")
    btQuery.WriteString("where 1 = 1 ")
    btQuery.WriteString("and name = `ali` ")
    db.Execute(query)

حالا تابع indent را در نظر بگیرید این تابع قرار است تغییرات زیادی را در خطوط مختلف یک رشته (byte array json) اعمال نماید. پس مناسب است از بافر استفاده شود و به همین خاطر تابع مورد نظر یک bytes.Buffer دریافت می‌کند و خروجی را در آن قرار می‌دهد.

تفاوت bytes.Buffer و strings.Builder در این است که bytes.Buffer عمومی‌تر می‌باشد ولی strings.Builder برای رشته استفاده می‌شود.


برای تمرین هر کدوم از بچه‌ها که میتونه یک بنچمارک بنویسه و در یک حلقه بزرگ مقدار موجود در یک رشته رو تغییر بده و همین کار رو یکبار با استفاده از bytes.Buffer و strings.Builder هم انجام بده و نتیجه مصرف memory رو با ما به اشتراک بذاره.



بهترین پاسخ
حامد نعیمایی ۲۰ مرداد ۱۴۰۲، ۲۲:۴۱