Одним из наиболее важных свойств Go является то, что канал - это первоклассное значение, которое может быть аллоцировано и передано куда угодно, как и любое другое значение. Общее использование этого свойства - это реализация безопасного параллельного демультиплексирования.
В примере из предыдущего поста handle
был идеализированным обработчиком для запроса, но мы не определили типа, который он обрабатывал. Если этот тип включает в себя канал по которому отвечать, каждый клиент может предоставить свой собственный путь для ответа. Вот схематическое определение типа Request
.
type Request struct {
args []int
f func([]int) int
resultChan chan int
}
Клиент предоставляет функцию и ее аргументы, а также канал внутри объекта запроса, по которому можно получить ответ.
func sum(a []int) (s int) {
for _, v := range a {
s += v
}
return
}
request := &Request{[]int{3, 4, 5}, sum, make(chan int)}
// Отправляем запрос (request)
clientRequests <- request
// Ждем ответ
fmt.Printf("answer: %d\n", <-request.resultChan)
На стороне сервера функция обработчика (handle function) - единственное, что изменяется.
func handle(queue chan *Request) {
for req := range queue {
req.resultChan <- req.f(req.args)
}
}
Очевидно, что еще многое предстоит сделать, чтобы сделать этот пример реалистичным, но этот код является основой для параллельной неблокирующей RPC системы с ограниченной скоростью пропуска сообщений, и здесь нет и следа мьютекса.
Читайте также:
Комментариев нет:
Отправить комментарий