ಕನ್ನಡ

ಗೋ ಭಾಷೆಯ ಕನ್ಕರೆನ್ಸಿ ವೈಶಿಷ್ಟ್ಯಗಳ ಕುರಿತು ಒಂದು ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ. ದಕ್ಷ ಮತ್ತು ಸ್ಕೇಲೆಬಲ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ನಿರ್ಮಿಸಲು ಗೋರೂಟೀನ್‌ಗಳು ಮತ್ತು ಚಾನೆಲ್‌ಗಳನ್ನು ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳೊಂದಿಗೆ ಅನ್ವೇಷಿಸುತ್ತದೆ.

ಗೋ ಕನ್ಕರೆನ್ಸಿ: ಗೋರೂಟೀನ್‌ಗಳು ಮತ್ತು ಚಾನೆಲ್‌ಗಳ ಶಕ್ತಿಯ ಅನಾವರಣ

ಗೋ, ಸಾಮಾನ್ಯವಾಗಿ ಗೋಲ್ಯಾಂಗ್ ಎಂದು ಕರೆಯಲ್ಪಡುತ್ತದೆ, ಅದರ ಸರಳತೆ, ದಕ್ಷತೆ, ಮತ್ತು ಕನ್ಕರೆನ್ಸಿಗಾಗಿ ಅಂತರ್ನಿರ್ಮಿತ ಬೆಂಬಲಕ್ಕೆ ಹೆಸರುವಾಸಿಯಾಗಿದೆ. ಕನ್ಕರೆನ್ಸಿ ಪ್ರೋಗ್ರಾಂಗಳಿಗೆ ಏಕಕಾಲದಲ್ಲಿ ಅನೇಕ ಕಾರ್ಯಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ, ಇದರಿಂದ ಕಾರ್ಯಕ್ಷಮತೆ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯಾಶೀಲತೆ ಸುಧಾರಿಸುತ್ತದೆ. ಗೋ ಇದನ್ನು ಎರಡು ಪ್ರಮುಖ ವೈಶಿಷ್ಟ್ಯಗಳ ಮೂಲಕ ಸಾಧಿಸುತ್ತದೆ: ಗೋರೂಟೀನ್‌ಗಳು ಮತ್ತು ಚಾನೆಲ್‌ಗಳು. ಈ ಬ್ಲಾಗ್ ಪೋಸ್ಟ್ ಈ ವೈಶಿಷ್ಟ್ಯಗಳ ಸಮಗ್ರ ಪರಿಶೋಧನೆಯನ್ನು ಒದಗಿಸುತ್ತದೆ, ಎಲ್ಲಾ ಹಂತದ ಡೆವಲಪರ್‌ಗಳಿಗೆ ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳು ಮತ್ತು ಒಳನೋಟಗಳನ್ನು ನೀಡುತ್ತದೆ.

ಕನ್ಕರೆನ್ಸಿ ಎಂದರೇನು?

ಕನ್ಕರೆನ್ಸಿ ಎಂದರೆ ಒಂದು ಪ್ರೋಗ್ರಾಂ ಏಕಕಾಲದಲ್ಲಿ ಅನೇಕ ಕಾರ್ಯಗಳನ್ನು ನಿರ್ವಹಿಸುವ ಸಾಮರ್ಥ್ಯ. ಕನ್ಕರೆನ್ಸಿಯನ್ನು ಪ್ಯಾರಲಲಿಸಂನಿಂದ ಪ್ರತ್ಯೇಕಿಸುವುದು ಮುಖ್ಯ. ಕನ್ಕರೆನ್ಸಿ ಎಂದರೆ ಒಂದೇ ಸಮಯದಲ್ಲಿ ಅನೇಕ ಕಾರ್ಯಗಳನ್ನು *ವ್ಯವಸ್ಥೆ ಮಾಡುವುದು*, ಆದರೆ ಪ್ಯಾರಲಲಿಸಂ ಎಂದರೆ ಒಂದೇ ಸಮಯದಲ್ಲಿ ಅನೇಕ ಕಾರ್ಯಗಳನ್ನು *ಮಾಡುವುದು*. ಒಂದೇ ಪ್ರೊಸೆಸರ್ ಕಾರ್ಯಗಳ ನಡುವೆ ವೇಗವಾಗಿ ಬದಲಾಯಿಸುವ ಮೂಲಕ ಕನ್ಕರೆನ್ಸಿಯನ್ನು ಸಾಧಿಸಬಹುದು, ಇದು ಏಕಕಾಲಿಕ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯ ಭ್ರಮೆಯನ್ನು ಸೃಷ್ಟಿಸುತ್ತದೆ. ಪ್ಯಾರಲಲಿಸಂ, ಮತ್ತೊಂದೆಡೆ, ಕಾರ್ಯಗಳನ್ನು ನಿಜವಾಗಿಯೂ ಏಕಕಾಲದಲ್ಲಿ ನಿರ್ವಹಿಸಲು ಬಹು ಪ್ರೊಸೆಸರ್‌ಗಳ ಅಗತ್ಯವಿರುತ್ತದೆ.

ಒಂದು ರೆಸ್ಟೋರೆಂಟ್‌ನಲ್ಲಿ ಬಾಣಸಿಗನನ್ನು ಕಲ್ಪಿಸಿಕೊಳ್ಳಿ. ಕನ್ಕರೆನ್ಸಿ ಎಂದರೆ ಬಾಣಸಿಗನು ತರಕಾರಿಗಳನ್ನು ಕತ್ತರಿಸುವುದು, ಸಾಸ್‌ಗಳನ್ನು ಕಲಕುವುದು ಮತ್ತು ಮಾಂಸವನ್ನು ಗ್ರಿಲ್ ಮಾಡುವಂತಹ ಕಾರ್ಯಗಳ ನಡುವೆ ಬದಲಾಯಿಸುವ ಮೂಲಕ ಅನೇಕ ಆರ್ಡರ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸುವಂತೆ. ಪ್ಯಾರಲಲಿಸಂ ಎಂದರೆ ಅನೇಕ ಬಾಣಸಿಗರು ಪ್ರತಿಯೊಬ್ಬರೂ ಒಂದೇ ಸಮಯದಲ್ಲಿ ಬೇರೆ ಬೇರೆ ಆರ್ಡರ್‌ನಲ್ಲಿ ಕೆಲಸ ಮಾಡುವಂತೆ.

ಗೋ-ನ ಕನ್ಕರೆನ್ಸಿ ಮಾದರಿಯು ಏಕ ಪ್ರೊಸೆಸರ್ ಅಥವಾ ಬಹು ಪ್ರೊಸೆಸರ್‌ಗಳಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆಯೇ ಎಂಬುದನ್ನು ಲೆಕ್ಕಿಸದೆ, ಕನ್ಕರೆಂಟ್ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಬರೆಯುವುದನ್ನು ಸುಲಭಗೊಳಿಸುವುದರ ಮೇಲೆ ಕೇಂದ್ರೀಕರಿಸುತ್ತದೆ. ಈ ನಮ್ಯತೆಯು ಸ್ಕೇಲೆಬಲ್ ಮತ್ತು ದಕ್ಷ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ನಿರ್ಮಿಸಲು ಪ್ರಮುಖ ಪ್ರಯೋಜನವಾಗಿದೆ.

ಗೋರೂಟೀನ್‌ಗಳು: ಹಗುರವಾದ ಥ್ರೆಡ್‌ಗಳು

ಒಂದು ಗೋರೂಟೀನ್ ಎನ್ನುವುದು ಹಗುರವಾದ, ಸ್ವತಂತ್ರವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವ ಫಂಕ್ಷನ್ ಆಗಿದೆ. ಇದನ್ನು ಥ್ರೆಡ್ ಎಂದು ಯೋಚಿಸಿ, ಆದರೆ ಹೆಚ್ಚು ದಕ್ಷವಾಗಿರುತ್ತದೆ. ಗೋರೂಟೀನ್ ರಚಿಸುವುದು ನಂಬಲಾಗದಷ್ಟು ಸರಳವಾಗಿದೆ: ಫಂಕ್ಷನ್ ಕರೆಯ ಮೊದಲು `go` ಕೀವರ್ಡ್ ಅನ್ನು ಸೇರಿಸಿ.

ಗೋರೂಟೀನ್‌ಗಳನ್ನು ರಚಿಸುವುದು

ಇಲ್ಲಿ ಒಂದು ಮೂಲಭೂತ ಉದಾಹರಣೆ ಇದೆ:

package main

import (
	"fmt"
	"time"
)

func sayHello(name string) {
	for i := 0; i < 5; i++ {
		fmt.Printf("Hello, %s! (Iteration %d)\n", name, i)
		time.Sleep(100 * time.Millisecond)
	}
}

func main() {
	go sayHello("Alice")
	go sayHello("Bob")

	// ಗೋರೂಟೀನ್‌ಗಳು ಕಾರ್ಯಗತಗೊಳ್ಳಲು ಸ್ವಲ್ಪ ಸಮಯ ಕಾಯಲು
	time.Sleep(500 * time.Millisecond)
	fmt.Println("ಮುಖ್ಯ ಫಂಕ್ಷನ್ ನಿರ್ಗಮಿಸುತ್ತಿದೆ")
}

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, `sayHello` ಫಂಕ್ಷನ್ ಅನ್ನು "Alice" ಗಾಗಿ ಒಂದು ಮತ್ತು "Bob" ಗಾಗಿ ಇನ್ನೊಂದು, ಎರಡು ಪ್ರತ್ಯೇಕ ಗೋರೂಟೀನ್‌ಗಳಾಗಿ ಪ್ರಾರಂಭಿಸಲಾಗಿದೆ. `main` ಫಂಕ್ಷನ್‌ನಲ್ಲಿರುವ `time.Sleep` ಮುಖ್ಯ ಫಂಕ್ಷನ್ ನಿರ್ಗಮಿಸುವ ಮೊದಲು ಗೋರೂಟೀನ್‌ಗಳಿಗೆ ಕಾರ್ಯಗತಗೊಳ್ಳಲು ಸಮಯವಿದೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಮುಖ್ಯವಾಗಿದೆ. ಅದು ಇಲ್ಲದಿದ್ದರೆ, ಗೋರೂಟೀನ್‌ಗಳು ಪೂರ್ಣಗೊಳ್ಳುವ ಮೊದಲೇ ಪ್ರೋಗ್ರಾಂ ಕೊನೆಗೊಳ್ಳಬಹುದು.

ಗೋರೂಟೀನ್‌ಗಳ ಪ್ರಯೋಜನಗಳು

ಚಾನೆಲ್‌ಗಳು: ಗೋರೂಟೀನ್‌ಗಳ ನಡುವಿನ ಸಂವಹನ

ಗೋರೂಟೀನ್‌ಗಳು ಕೋಡ್ ಅನ್ನು ಏಕಕಾಲದಲ್ಲಿ ಕಾರ್ಯಗತಗೊಳಿಸಲು ಒಂದು ಮಾರ್ಗವನ್ನು ಒದಗಿಸಿದರೆ, ಅವುಗಳು ಪರಸ್ಪರ ಸಂವಹನ ಮತ್ತು ಸಿಂಕ್ರೊನೈಸ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ. ಇಲ್ಲಿಯೇ ಚಾನೆಲ್‌ಗಳು ಬರುತ್ತವೆ. ಚಾನೆಲ್ ಎನ್ನುವುದು ಒಂದು ಟೈಪ್ಡ್ ಕಂಡ್ಯೂಟ್ ಆಗಿದ್ದು, ಅದರ ಮೂಲಕ ನೀವು ಗೋರೂಟೀನ್‌ಗಳ ನಡುವೆ ಮೌಲ್ಯಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಮತ್ತು ಸ್ವೀಕರಿಸಬಹುದು.

ಚಾನೆಲ್‌ಗಳನ್ನು ರಚಿಸುವುದು

ಚಾನೆಲ್‌ಗಳನ್ನು `make` ಫಂಕ್ಷನ್ ಬಳಸಿ ರಚಿಸಲಾಗುತ್ತದೆ:

ch := make(chan int) // ಪೂರ್ಣಾಂಕಗಳನ್ನು ರವಾನಿಸಬಲ್ಲ ಚಾನೆಲ್ ಅನ್ನು ರಚಿಸುತ್ತದೆ

ನೀವು ಬಫರ್ಡ್ ಚಾನೆಲ್‌ಗಳನ್ನು ಸಹ ರಚಿಸಬಹುದು, ಅದು ಸ್ವೀಕರಿಸುವವರು ಸಿದ್ಧರಿಲ್ಲದಿದ್ದರೂ ನಿರ್ದಿಷ್ಟ ಸಂಖ್ಯೆಯ ಮೌಲ್ಯಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಬಹುದು:

ch := make(chan int, 10) // 10 ಸಾಮರ್ಥ್ಯದ ಬಫರ್ಡ್ ಚಾನೆಲ್ ಅನ್ನು ರಚಿಸುತ್ತದೆ

ಡೇಟಾ ಕಳುಹಿಸುವುದು ಮತ್ತು ಸ್ವೀಕರಿಸುವುದು

ಡೇಟಾವನ್ನು ಚಾನೆಲ್‌ಗೆ `<-` ಆಪರೇಟರ್ ಬಳಸಿ ಕಳುಹಿಸಲಾಗುತ್ತದೆ:

ch <- 42 // ch ಚಾನೆಲ್‌ಗೆ 42 ಮೌಲ್ಯವನ್ನು ಕಳುಹಿಸುತ್ತದೆ

ಡೇಟಾವನ್ನು ಚಾನೆಲ್‌ನಿಂದ `<-` ಆಪರೇಟರ್ ಬಳಸಿ ಸ್ವೀಕರಿಸಲಾಗುತ್ತದೆ:

value := <-ch // ch ಚಾನೆಲ್‌ನಿಂದ ಮೌಲ್ಯವನ್ನು ಸ್ವೀಕರಿಸಿ ಅದನ್ನು value ವೇರಿಯೇಬಲ್‌ಗೆ ನಿಯೋಜಿಸುತ್ತದೆ

ಉದಾಹರಣೆ: ಗೋರೂಟೀನ್‌ಗಳನ್ನು ಸಂಯೋಜಿಸಲು ಚಾನೆಲ್‌ಗಳನ್ನು ಬಳಸುವುದು

ಚಾನೆಲ್‌ಗಳನ್ನು ಗೋರೂಟೀನ್‌ಗಳನ್ನು ಸಂಯೋಜಿಸಲು ಹೇಗೆ ಬಳಸಬಹುದು ಎಂಬುದನ್ನು ಪ್ರದರ್ಶಿಸುವ ಉದಾಹರಣೆ ಇಲ್ಲಿದೆ:

package main

import (
	"fmt"
	"time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
	for j := range jobs {
		fmt.Printf("ವರ್ಕರ್ %d ಜಾಬ್ %d ಅನ್ನು ಪ್ರಾರಂಭಿಸಿದೆ\n", id, j)
		time.Sleep(time.Second)
		fmt.Printf("ವರ್ಕರ್ %d ಜಾಬ್ %d ಅನ್ನು ಮುಗಿಸಿದೆ\n", id, j)
		results <- j * 2
	}
}

func main() {
	jobs := make(chan int, 100)
	results := make(chan int, 100)

	// 3 ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಿ
	for w := 1; w <= 3; w++ {
		go worker(w, jobs, results)
	}

	// jobs ಚಾನೆಲ್‌ಗೆ 5 ಜಾಬ್‌ಗಳನ್ನು ಕಳುಹಿಸಿ
	for j := 1; j <= 5; j++ {
		jobs <- j
	}
	close(jobs)

	// results ಚಾನೆಲ್‌ನಿಂದ ಫಲಿತಾಂಶಗಳನ್ನು ಸಂಗ್ರಹಿಸಿ
	for a := 1; a <= 5; a++ {
		fmt.Println("ಫಲಿತಾಂಶ:", <-results)
	}
}

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ:

ಈ ಉದಾಹರಣೆಯು ಅನೇಕ ಗೋರೂಟೀನ್‌ಗಳ ನಡುವೆ ಕೆಲಸವನ್ನು ವಿತರಿಸಲು ಮತ್ತು ಫಲಿತಾಂಶಗಳನ್ನು ಸಂಗ್ರಹಿಸಲು ಚಾನೆಲ್‌ಗಳನ್ನು ಹೇಗೆ ಬಳಸಬಹುದು ಎಂಬುದನ್ನು ಪ್ರದರ್ಶಿಸುತ್ತದೆ. `jobs` ಚಾನೆಲ್ ಅನ್ನು ಮುಚ್ಚುವುದು ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳಿಗೆ ಇನ್ನು ಸಂಸ್ಕರಿಸಲು ಜಾಬ್‌ಗಳಿಲ್ಲ ಎಂದು ಸಂಕೇತಿಸಲು ನಿರ್ಣಾಯಕವಾಗಿದೆ. ಚಾನೆಲ್ ಅನ್ನು ಮುಚ್ಚದಿದ್ದರೆ, ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳು ಹೆಚ್ಚಿನ ಜಾಬ್‌ಗಳಿಗಾಗಿ ಅನಿರ್ದಿಷ್ಟವಾಗಿ ಕಾಯುತ್ತಾ ನಿರ್ಬಂಧಿಸಲ್ಪಡುತ್ತವೆ.

ಸೆಲೆಕ್ಟ್ ಸ್ಟೇಟ್‌ಮೆಂಟ್: ಬಹು ಚಾನೆಲ್‌ಗಳ ಮೇಲೆ ಮಲ್ಟಿಪ್ಲೆಕ್ಸಿಂಗ್

`select` ಸ್ಟೇಟ್‌ಮೆಂಟ್ ಏಕಕಾಲದಲ್ಲಿ ಅನೇಕ ಚಾನೆಲ್ ಕಾರ್ಯಾಚರಣೆಗಳಿಗಾಗಿ ಕಾಯಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಒಂದು ಕೇಸ್ ಮುಂದುವರೆಯಲು ಸಿದ್ಧವಾಗುವವರೆಗೆ ಇದು ನಿರ್ಬಂಧಿಸುತ್ತದೆ. ಅನೇಕ ಕೇಸ್‌ಗಳು ಸಿದ್ಧವಾಗಿದ್ದರೆ, ಒಂದನ್ನು ಯಾದೃಚ್ಛಿಕವಾಗಿ ಆಯ್ಕೆಮಾಡಲಾಗುತ್ತದೆ.

ಉದಾಹರಣೆ: ಬಹು ಚಾನೆಲ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಸೆಲೆಕ್ಟ್ ಬಳಸುವುದು

package main

import (
	"fmt"
	"time"
)

func main() {
	c1 := make(chan string, 1)
	c2 := make(chan string, 1)

	go func() {
		time.Sleep(2 * time.Second)
		c1 <- "ಚಾನೆಲ್ 1 ರಿಂದ ಸಂದೇಶ"
	}()

	go func() {
		time.Sleep(1 * time.Second)
		c2 <- "ಚಾನೆಲ್ 2 ರಿಂದ ಸಂದೇಶ"
	}()

	for i := 0; i < 2; i++ {
		select {
		case msg1 := <-c1:
			fmt.Println("ಸ್ವೀಕರಿಸಲಾಗಿದೆ:", msg1)
		case msg2 := <-c2:
			fmt.Println("ಸ್ವೀಕರಿಸಲಾಗಿದೆ:", msg2)
		case <-time.After(3 * time.Second):
			fmt.Println("ಸಮಯ ಮೀರಿದೆ")
			return
		}
	}
}

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ:

`select` ಸ್ಟೇಟ್‌ಮೆಂಟ್ ಅನೇಕ ಕನ್ಕರೆಂಟ್ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಮತ್ತು ಒಂದೇ ಚಾನೆಲ್‌ನಲ್ಲಿ ಅನಿರ್ದಿಷ್ಟವಾಗಿ ನಿರ್ಬಂಧಿಸುವುದನ್ನು ತಪ್ಪಿಸಲು ಒಂದು ಶಕ್ತಿಯುತ ಸಾಧನವಾಗಿದೆ. `time.After` ಫಂಕ್ಷನ್ ಟೈಮ್‌ಔಟ್‌ಗಳನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಮತ್ತು ಡೆಡ್‌ಲಾಕ್‌ಗಳನ್ನು ತಡೆಯಲು ವಿಶೇಷವಾಗಿ ಉಪಯುಕ್ತವಾಗಿದೆ.

ಗೋ-ನಲ್ಲಿ ಸಾಮಾನ್ಯ ಕನ್ಕರೆನ್ಸಿ ಪ್ಯಾಟರ್ನ್‌ಗಳು

ಗೋ-ನ ಕನ್ಕರೆನ್ಸಿ ವೈಶಿಷ್ಟ್ಯಗಳು ಹಲವಾರು ಸಾಮಾನ್ಯ ಪ್ಯಾಟರ್ನ್‌ಗಳಿಗೆ ಅನುಕೂಲ ಮಾಡಿಕೊಡುತ್ತವೆ. ಈ ಪ್ಯಾಟರ್ನ್‌ಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಹೆಚ್ಚು ದೃಢವಾದ ಮತ್ತು ದಕ್ಷವಾದ ಕನ್ಕರೆಂಟ್ ಕೋಡ್ ಬರೆಯಲು ನಿಮಗೆ ಸಹಾಯ ಮಾಡುತ್ತದೆ.

ವರ್ಕರ್ ಪೂಲ್‌ಗಳು

ಹಿಂದಿನ ಉದಾಹರಣೆಯಲ್ಲಿ ಪ್ರದರ್ಶಿಸಿದಂತೆ, ವರ್ಕರ್ ಪೂಲ್‌ಗಳು ಹಂಚಿದ ಕ್ಯೂ (ಚಾನೆಲ್) ನಿಂದ ಕಾರ್ಯಗಳನ್ನು ಸಂಸ್ಕರಿಸುವ ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳ ಗುಂಪನ್ನು ಒಳಗೊಂಡಿರುತ್ತವೆ. ಈ ಪ್ಯಾಟರ್ನ್ ಅನೇಕ ಪ್ರೊಸೆಸರ್‌ಗಳ ನಡುವೆ ಕೆಲಸವನ್ನು ವಿತರಿಸಲು ಮತ್ತು ಥ್ರೋಪುಟ್ ಅನ್ನು ಸುಧಾರಿಸಲು ಉಪಯುಕ್ತವಾಗಿದೆ. ಉದಾಹರಣೆಗಳು ಸೇರಿವೆ:

ಫ್ಯಾನ್-ಔಟ್, ಫ್ಯಾನ್-ಇನ್

ಈ ಪ್ಯಾಟರ್ನ್ ಕೆಲಸವನ್ನು ಅನೇಕ ಗೋರೂಟೀನ್‌ಗಳಿಗೆ ವಿತರಿಸುವುದು (ಫ್ಯಾನ್-ಔಟ್) ಮತ್ತು ನಂತರ ಫಲಿತಾಂಶಗಳನ್ನು ಒಂದೇ ಚಾನೆಲ್‌ಗೆ ಸಂಯೋಜಿಸುವುದು (ಫ್ಯಾನ್-ಇನ್) ಒಳಗೊಂಡಿರುತ್ತದೆ. ಇದನ್ನು ಹೆಚ್ಚಾಗಿ ಡೇಟಾದ ಸಮಾನಾಂತರ ಸಂಸ್ಕರಣೆಗಾಗಿ ಬಳಸಲಾಗುತ್ತದೆ.

ಫ್ಯಾನ್-ಔಟ್: ಡೇಟಾವನ್ನು ಏಕಕಾಲದಲ್ಲಿ ಸಂಸ್ಕರಿಸಲು ಅನೇಕ ಗೋರೂಟೀನ್‌ಗಳನ್ನು ಹುಟ್ಟುಹಾಕಲಾಗುತ್ತದೆ. ಪ್ರತಿಯೊಂದು ಗೋರೂಟೀನ್ ಸಂಸ್ಕರಿಸಲು ಡೇಟಾದ ಒಂದು ಭಾಗವನ್ನು ಪಡೆಯುತ್ತದೆ.

ಫ್ಯಾನ್-ಇನ್: ಒಂದೇ ಗೋರೂಟೀನ್ ಎಲ್ಲಾ ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳಿಂದ ಫಲಿತಾಂಶಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ ಮತ್ತು ಅವುಗಳನ್ನು ಒಂದೇ ಫಲಿತಾಂಶಕ್ಕೆ ಸಂಯೋಜಿಸುತ್ತದೆ. ಇದು ಹೆಚ್ಚಾಗಿ ವರ್ಕರ್‌ಗಳಿಂದ ಫಲಿತಾಂಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಚಾನೆಲ್ ಅನ್ನು ಬಳಸುವುದನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ.

ಉದಾಹರಣೆ ಸನ್ನಿವೇಶಗಳು:

ಪೈಪ್‌ಲೈನ್‌ಗಳು

ಪೈಪ್‌ಲೈನ್ ಎನ್ನುವುದು ಹಂತಗಳ ಸರಣಿಯಾಗಿದ್ದು, ಪ್ರತಿ ಹಂತವು ಹಿಂದಿನ ಹಂತದಿಂದ ಡೇಟಾವನ್ನು ಸಂಸ್ಕರಿಸುತ್ತದೆ ಮತ್ತು ಫಲಿತಾಂಶವನ್ನು ಮುಂದಿನ ಹಂತಕ್ಕೆ ಕಳುಹಿಸುತ್ತದೆ. ಸಂಕೀರ್ಣ ಡೇಟಾ ಸಂಸ್ಕರಣಾ ವರ್ಕ್‌ಫ್ಲೋಗಳನ್ನು ರಚಿಸಲು ಇದು ಉಪಯುಕ್ತವಾಗಿದೆ. ಪ್ರತಿ ಹಂತವು ಸಾಮಾನ್ಯವಾಗಿ ತನ್ನದೇ ಆದ ಗೋರೂಟೀನ್‌ನಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಮತ್ತು ಚಾನೆಲ್‌ಗಳ ಮೂಲಕ ಇತರ ಹಂತಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸುತ್ತದೆ.

ಉದಾಹರಣೆ ಬಳಕೆಯ ಪ್ರಕರಣಗಳು:

ಕನ್ಕರೆಂಟ್ ಗೋ ಪ್ರೋಗ್ರಾಂಗಳಲ್ಲಿ ದೋಷ ನಿರ್ವಹಣೆ

ಕನ್ಕರೆಂಟ್ ಪ್ರೋಗ್ರಾಂಗಳಲ್ಲಿ ದೋಷ ನಿರ್ವಹಣೆ ನಿರ್ಣಾಯಕವಾಗಿದೆ. ಒಂದು ಗೋರೂಟೀನ್ ದೋಷವನ್ನು ಎದುರಿಸಿದಾಗ, ಅದನ್ನು ಸರಿಯಾಗಿ ನಿರ್ವಹಿಸುವುದು ಮತ್ತು ಇಡೀ ಪ್ರೋಗ್ರಾಂ ಕ್ರ್ಯಾಶ್ ಆಗುವುದನ್ನು ತಡೆಯುವುದು ಮುಖ್ಯ. ಇಲ್ಲಿ ಕೆಲವು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳಿವೆ:

ಉದಾಹರಣೆ: ಚಾನೆಲ್‌ಗಳೊಂದಿಗೆ ದೋಷ ನಿರ್ವಹಣೆ

package main

import (
	"fmt"
	"time"
)

func worker(id int, jobs <-chan int, results chan<- int, errs chan<- error) {
	for j := range jobs {
		fmt.Printf("ವರ್ಕರ್ %d ಜಾಬ್ %d ಅನ್ನು ಪ್ರಾರಂಭಿಸಿದೆ\n", id, j)
		time.Sleep(time.Second)
		fmt.Printf("ವರ್ಕರ್ %d ಜಾಬ್ %d ಅನ್ನು ಮುಗಿಸಿದೆ\n", id, j)
		if j%2 == 0 { // ಸಮ ಸಂಖ್ಯೆಗಳಿಗೆ ದೋಷವನ್ನು ಅನುಕರಿಸುವುದು
			errs <- fmt.Errorf("ವರ್ಕರ್ %d: ಜಾಬ್ %d ವಿಫಲವಾಯಿತು", id, j)
			results <- 0 // ಪ್ಲೇಸ್‌ಹೋಲ್ಡರ್ ಫಲಿತಾಂಶವನ್ನು ಕಳುಹಿಸುವುದು
		} else {
			results <- j * 2
		}
	}
}

func main() {
	jobs := make(chan int, 100)
	results := make(chan int, 100)
	errs := make(chan error, 100)

	// 3 ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಿ
	for w := 1; w <= 3; w++ {
		go worker(w, jobs, results, errs)
	}

	// jobs ಚಾನೆಲ್‌ಗೆ 5 ಜಾಬ್‌ಗಳನ್ನು ಕಳುಹಿಸಿ
	for j := 1; j <= 5; j++ {
		jobs <- j
	}
	close(jobs)

	// ಫಲಿತಾಂಶಗಳು ಮತ್ತು ದೋಷಗಳನ್ನು ಸಂಗ್ರಹಿಸಿ
	for a := 1; a <= 5; a++ {
		select {
		case res := <-results:
			fmt.Println("ಫಲಿತಾಂಶ:", res)
		case err := <-errs:
			fmt.Println("ದೋಷ:", err)
		}
	}
}

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳಿಂದ ಮುಖ್ಯ ಫಂಕ್ಷನ್‌ಗೆ ದೋಷ ಸಂದೇಶಗಳನ್ನು ರವಾನಿಸಲು ನಾವು `errs` ಚಾನೆಲ್ ಅನ್ನು ಸೇರಿಸಿದ್ದೇವೆ. ವರ್ಕರ್ ಗೋರೂಟೀನ್ ಸಮ-ಸಂಖ್ಯೆಯ ಜಾಬ್‌ಗಳಿಗೆ ದೋಷವನ್ನು ಅನುಕರಿಸುತ್ತದೆ, `errs` ಚಾನೆಲ್‌ನಲ್ಲಿ ದೋಷ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸುತ್ತದೆ. ಮುಖ್ಯ ಫಂಕ್ಷನ್ ನಂತರ ಪ್ರತಿ ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ನಿಂದ ಫಲಿತಾಂಶ ಅಥವಾ ದೋಷವನ್ನು ಸ್ವೀಕರಿಸಲು `select` ಸ್ಟೇಟ್‌ಮೆಂಟ್ ಅನ್ನು ಬಳಸುತ್ತದೆ.

ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಪ್ರಿಮಿಟಿವ್ಸ್: ಮ್ಯೂಟೆಕ್ಸ್‌ಗಳು ಮತ್ತು ವೇಟ್‌ಗ್ರೂಪ್‌ಗಳು

ಚಾನೆಲ್‌ಗಳು ಗೋರೂಟೀನ್‌ಗಳ ನಡುವೆ ಸಂವಹನ ನಡೆಸಲು ಆದ್ಯತೆಯ ಮಾರ್ಗವಾಗಿದ್ದರೂ, ಕೆಲವೊಮ್ಮೆ ನಿಮಗೆ ಹಂಚಿದ ಸಂಪನ್ಮೂಲಗಳ ಮೇಲೆ ನೇರ ನಿಯಂತ್ರಣ ಬೇಕಾಗುತ್ತದೆ. ಗೋ ಈ ಉದ್ದೇಶಕ್ಕಾಗಿ ಮ್ಯೂಟೆಕ್ಸ್‌ಗಳು ಮತ್ತು ವೇಟ್‌ಗ್ರೂಪ್‌ಗಳಂತಹ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಪ್ರಿಮಿಟಿವ್ಸ್‌ಗಳನ್ನು ಒದಗಿಸುತ್ತದೆ.

ಮ್ಯೂಟೆಕ್ಸ್‌ಗಳು

ಒಂದು ಮ್ಯೂಟೆಕ್ಸ್ (ಮ್ಯೂಚುಯಲ್ ಎಕ್ಸ್‌ಕ್ಲೂಷನ್ ಲಾಕ್) ಹಂಚಿದ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಏಕಕಾಲಿಕ ಪ್ರವೇಶದಿಂದ ರಕ್ಷಿಸುತ್ತದೆ. ಒಂದೇ ಸಮಯದಲ್ಲಿ ಕೇವಲ ಒಂದು ಗೋರೂಟೀನ್ ಮಾತ್ರ ಲಾಕ್ ಅನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಬಹುದು. ಇದು ಡೇಟಾ ರೇಸ್‌ಗಳನ್ನು ತಡೆಯುತ್ತದೆ ಮತ್ತು ಡೇಟಾ ಸ್ಥಿರತೆಯನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ.

package main

import (
	"fmt"
	"sync"
)

var ( // ಹಂಚಿದ ಸಂಪನ್ಮೂಲ
	counter int
	m sync.Mutex
)

func increment() {
	m.Lock() // ಲಾಕ್ ಅನ್ನು ಪಡೆದುಕೊಳ್ಳಿ
	counter++
	fmt.Println("ಕೌಂಟರ್ ಇಲ್ಲಿಗೆ ಹೆಚ್ಚಿಸಲಾಗಿದೆ:", counter)
	m.Unlock() // ಲಾಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡಿ
}

func main() {
	var wg sync.WaitGroup

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			increment()
		}()
	}

	wg.Wait() // ಎಲ್ಲಾ ಗೋರೂಟೀನ್‌ಗಳು ಮುಗಿಯುವವರೆಗೆ ಕಾಯಿರಿ
	fmt.Println("ಅಂತಿಮ ಕೌಂಟರ್ ಮೌಲ್ಯ:", counter)
}

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, `increment` ಫಂಕ್ಷನ್ `counter` ವೇರಿಯೇಬಲ್ ಅನ್ನು ಏಕಕಾಲಿಕ ಪ್ರವೇಶದಿಂದ ರಕ್ಷಿಸಲು ಮ್ಯೂಟೆಕ್ಸ್ ಅನ್ನು ಬಳಸುತ್ತದೆ. `m.Lock()` ವಿಧಾನವು ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸುವ ಮೊದಲು ಲಾಕ್ ಅನ್ನು ಪಡೆದುಕೊಳ್ಳುತ್ತದೆ, ಮತ್ತು `m.Unlock()` ವಿಧಾನವು ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸಿದ ನಂತರ ಲಾಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡುತ್ತದೆ. ಇದು ಒಂದೇ ಸಮಯದಲ್ಲಿ ಕೇವಲ ಒಂದು ಗೋರೂಟೀನ್ ಮಾತ್ರ ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸಬಲ್ಲದು ಎಂದು ಖಚಿತಪಡಿಸುತ್ತದೆ, ಡೇಟಾ ರೇಸ್‌ಗಳನ್ನು ತಡೆಯುತ್ತದೆ.

ವೇಟ್‌ಗ್ರೂಪ್‌ಗಳು

ಒಂದು ವೇಟ್‌ಗ್ರೂಪ್ ಗೋರೂಟೀನ್‌ಗಳ ಸಂಗ್ರಹವು ಮುಗಿಯುವವರೆಗೆ ಕಾಯಲು ಬಳಸಲಾಗುತ್ತದೆ. ಇದು ಮೂರು ವಿಧಾನಗಳನ್ನು ಒದಗಿಸುತ್ತದೆ:

ಹಿಂದಿನ ಉದಾಹರಣೆಯಲ್ಲಿ, `sync.WaitGroup` ಮುಖ್ಯ ಫಂಕ್ಷನ್ ಅಂತಿಮ ಕೌಂಟರ್ ಮೌಲ್ಯವನ್ನು ಮುದ್ರಿಸುವ ಮೊದಲು ಎಲ್ಲಾ 100 ಗೋರೂಟೀನ್‌ಗಳು ಮುಗಿಯುವವರೆಗೆ ಕಾಯುತ್ತದೆ ಎಂದು ಖಚಿತಪಡಿಸುತ್ತದೆ. `wg.Add(1)` ಪ್ರತಿ ಪ್ರಾರಂಭಿಸಲಾದ ಗೋರೂಟೀನ್‌ಗೆ ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ. `defer wg.Done()` ಒಂದು ಗೋರೂಟೀನ್ ಪೂರ್ಣಗೊಂಡಾಗ ಕೌಂಟರ್ ಅನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ, ಮತ್ತು `wg.Wait()` ಎಲ್ಲಾ ಗೋರೂಟೀನ್‌ಗಳು ಮುಗಿಯುವವರೆಗೆ (ಕೌಂಟರ್ ಶೂನ್ಯವನ್ನು ತಲುಪುವವರೆಗೆ) ನಿರ್ಬಂಧಿಸುತ್ತದೆ.

ಕಾಂಟೆಕ್ಸ್ಟ್: ಗೋರೂಟೀನ್‌ಗಳು ಮತ್ತು ರದ್ದತಿಯನ್ನು ನಿರ್ವಹಿಸುವುದು

`context` ಪ್ಯಾಕೇಜ್ ಗೋರೂಟೀನ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಮತ್ತು ರದ್ದತಿ ಸಂಕೇತಗಳನ್ನು ಪ್ರಸಾರ ಮಾಡಲು ಒಂದು ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತದೆ. ದೀರ್ಘಕಾಲದ ಕಾರ್ಯಾಚರಣೆಗಳಿಗೆ ಅಥವಾ ಬಾಹ್ಯ ಘಟನೆಗಳ ಆಧಾರದ ಮೇಲೆ ರದ್ದುಗೊಳಿಸಬೇಕಾದ ಕಾರ್ಯಾಚರಣೆಗಳಿಗೆ ಇದು ವಿಶೇಷವಾಗಿ ಉಪಯುಕ್ತವಾಗಿದೆ.

ಉದಾಹರಣೆ: ರದ್ದತಿಗಾಗಿ ಕಾಂಟೆಕ್ಸ್ಟ್ ಬಳಸುವುದು

package main

import (
	"context"
	"fmt"
	"time"
)

func worker(ctx context.Context, id int) {
	for {
		select {
		case <-ctx.Done():
			fmt.Printf("ವರ್ಕರ್ %d: ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ\n", id)
			return
		default:
			fmt.Printf("ವರ್ಕರ್ %d: ಕೆಲಸ ಮಾಡುತ್ತಿದೆ...\n", id)
			time.Sleep(time.Second)
		}
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	// 3 ವರ್ಕರ್ ಗೋರೂಟೀನ್‌ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಿ
	for w := 1; w <= 3; w++ {
		go worker(ctx, w)
	}

	// 5 ಸೆಕೆಂಡುಗಳ ನಂತರ ಕಾಂಟೆಕ್ಸ್ಟ್ ಅನ್ನು ರದ್ದುಗೊಳಿಸಿ
	time.Sleep(5 * time.Second)
	fmt.Println("ಕಾಂಟೆಕ್ಸ್ಟ್ ಅನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗುತ್ತಿದೆ...")
	cancel()

	// ವರ್ಕರ್‌ಗಳು ನಿರ್ಗಮಿಸಲು ಸ್ವಲ್ಪ ಸಮಯ ಕಾಯಿರಿ
	time.Sleep(2 * time.Second)
	fmt.Println("ಮುಖ್ಯ ಫಂಕ್ಷನ್ ನಿರ್ಗಮಿಸುತ್ತಿದೆ")
}

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ:

ಕಾಂಟೆಕ್ಸ್ಟ್‌ಗಳನ್ನು ಬಳಸುವುದರಿಂದ ಗೋರೂಟೀನ್‌ಗಳು ಇನ್ನು ಮುಂದೆ ಅಗತ್ಯವಿಲ್ಲದಿದ್ದಾಗ ಅವುಗಳನ್ನು ಸರಿಯಾಗಿ ಸ್ಥಗಿತಗೊಳಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ, ಸಂಪನ್ಮೂಲ ಸೋರಿಕೆಯನ್ನು ತಡೆಯುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ ಪ್ರೋಗ್ರಾಂಗಳ ವಿಶ್ವಾಸಾರ್ಹತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ.

ಗೋ ಕನ್ಕರೆನ್ಸಿಯ ನೈಜ-ಪ್ರಪಂಚದ ಅನ್ವಯಗಳು

ಗೋ-ನ ಕನ್ಕರೆನ್ಸಿ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ವ್ಯಾಪಕ ಶ್ರೇಣಿಯ ನೈಜ-ಪ್ರಪಂಚದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಲ್ಲಿ ಬಳಸಲಾಗುತ್ತದೆ, ಅವುಗಳೆಂದರೆ:

ಗೋ ಕನ್ಕರೆನ್ಸಿಗಾಗಿ ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು

ಕನ್ಕರೆಂಟ್ ಗೋ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಬರೆಯುವಾಗ ನೆನಪಿನಲ್ಲಿಡಬೇಕಾದ ಕೆಲವು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು ಇಲ್ಲಿವೆ:

ತೀರ್ಮಾನ

ಗೋ-ನ ಕನ್ಕರೆನ್ಸಿ ವೈಶಿಷ್ಟ್ಯಗಳು, ವಿಶೇಷವಾಗಿ ಗೋರೂಟೀನ್‌ಗಳು ಮತ್ತು ಚಾನೆಲ್‌ಗಳು, ಕನ್ಕರೆಂಟ್ ಮತ್ತು ಸಮಾನಾಂತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ನಿರ್ಮಿಸಲು ಶಕ್ತಿಯುತ ಮತ್ತು ದಕ್ಷ ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತವೆ. ಈ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವ ಮೂಲಕ ಮತ್ತು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳನ್ನು ಅನುಸರಿಸುವ ಮೂಲಕ, ನೀವು ದೃಢವಾದ, ಸ್ಕೇಲೆಬಲ್ ಮತ್ತು ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಬರೆಯಬಹುದು. ಈ ಉಪಕರಣಗಳನ್ನು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ಬಳಸಿಕೊಳ್ಳುವ ಸಾಮರ್ಥ್ಯವು ಆಧುನಿಕ ಸಾಫ್ಟ್‌ವೇರ್ ಅಭಿವೃದ್ಧಿಗೆ, ವಿಶೇಷವಾಗಿ ವಿತರಿಸಿದ ವ್ಯವಸ್ಥೆಗಳು ಮತ್ತು ಕ್ಲೌಡ್ ಕಂಪ್ಯೂಟಿಂಗ್ ಪರಿಸರದಲ್ಲಿ ನಿರ್ಣಾಯಕ ಕೌಶಲ್ಯವಾಗಿದೆ. ಗೋ-ನ ವಿನ್ಯಾಸವು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಸುಲಭ ಮತ್ತು ಕಾರ್ಯಗತಗೊಳಿಸಲು ದಕ್ಷವಾಗಿರುವ ಕನ್ಕರೆಂಟ್ ಕೋಡ್ ಬರೆಯುವುದನ್ನು ಉತ್ತೇಜಿಸುತ್ತದೆ.