Sobes.tech
Middle

Чӣ оқибатҳо метавонанд ҳангоми хондан аз канали баста дар Go пайдо шаванд?

sobes.tech AI

Ҷавоб аз AI

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

package main

import (
	"fmt"
)

func main() {
	ch := make(chan int, 1) // کانال با بافر
	ch <- 1
	close(ch)

	val, ok := <-ch // خواندن از کانال بسته
	fmt.Printf("مقدار: %d, باز است: %t\n", val, ok) // خروجی "مقدار: 1, باز است: true"

	val, ok = <-ch // خواندن مجدد از همان کانال بسته
	fmt.Printf("مقدار: %d, باز است: %t\n", val, ok) // خروجی "مقدار: 0, باز است: false"

	// خواندن‌های بعدی از کانال بسته
	val, ok = <-ch
	fmt.Printf("مقدار: %d, باز است: %t\n", val, ok) // خروجی "مقدار: 0, باز است: false"
}

عواقب اصلی:

  • دریافت مقدار صفر: برنامه سقوط نمی‌کند، اما مقدار صفر پیش‌فرض برای نوع داده‌های کانال را دریافت می‌کند.
  • شاخص بسته بودن: پارامتر بولی دوم، در صورت استفاده، false می‌شود، که نشان می‌دهد کانال بسته شده و مقدار دریافتی صفر است.
  • خواندن غیر بلوکه‌کننده: عملیات خواندن بلوکه نمی‌کند.
  • بدون پانیک: بر خلاف نوشتن در کانال بسته، خواندن از کانال بسته پانیک ایجاد نمی‌کند.

مقایسه خواندن از کانال باز و بسته:

وضعیت کانال عملیات رفتار مقدار بازگردانده شده (در صورت وجود پارامتر دوم)
باز <-ch بلوکه تا دریافت مقدار یا بسته شدن مقدار، true
باز val, ok := <-ch بلوکه تا دریافت مقدار یا بسته شدن مقدار، true
بسته شده <-ch دریافت فوری مقدار صفر
بسته شده val, ok := <-ch دریافت فوری مقدار صفر، false

استفاده از پارامتر بولی دوم روشی توصیه‌شده برای تعیین موفقیت‌آمیز بودن دریافت عنصر واقعی از کانال یا بسته بودن کانال است.

package main

import (
	"fmt"
)

func main() {
	ch := make(chan int, 1)
	ch <- 1
	close(ch)

	برای {
		val, ok := <-ch
		اگر !ok {
			fmt.Println("کانال بسته شده، خروج از حلقه.")
			break
		}
		fmt.Printf("مقدار دریافت شده: %d\n", val)
	}
}

این رفتار اجازه می‌دهد به طور مؤثر کار goroutine‌هایی که از کانال می‌خوانند پس از بسته شدن آن، خاتمه یابد.