Решение на Concurrent Tasks от Даниел Тасков

Обратно към всички решения

Към профила на Даниел Тасков

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 10 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"sync"
)
type empty struct{}
type semaphore chan empty
type book struct {
ISBN string `xml:"isbn,attr"`
Title string `xml:"title"`
Genre string `xml:"genre"`
Author struct {
First_name string `xml:"first_name"`
Last_name string `xml:"last_name"`
} `xml:"author"`
copies struct {
available, registered int
}
}
func (b *book) String() string {
return "[" + b.ISBN + "] " + b.Title + " от " +
b.Author.First_name + " " + b.Author.Last_name
}
type Bibliotheke struct {
librarians semaphore
books map[string]book
sync.Mutex
}
func NewLibrary(librarians int) Library {
var b *Bibliotheke = new(Bibliotheke)
b.librarians = make(semaphore, librarians)
b.books = map[string]book{}
return b
}
func (b *Bibliotheke) AddBook(book book) (int, error) {
b.Lock()
defer b.Unlock()
if _, ok := b.books[book.ISBN]; ok {
book.copies = b.books[book.ISBN].copies
}
if book.copies.registered == 4 {
return book.copies.registered, fmt.Errorf("Има 4 копия на книга %s", book.ISBN)
}
book.copies.registered += 1
book.copies.available += 1
b.books[book.ISBN] = book
return book.copies.registered, nil
}
func (b *Bibliotheke) AddBookJSON(Data []byte) (int, error) {
var book book
if err := json.Unmarshal(Data, &book); err != nil {
fmt.Errorf("%s", err)
}
return b.AddBook(book)
}
func (b *Bibliotheke) AddBookXML(Data []byte) (int, error) {
var book book
if err := xml.Unmarshal(Data, &book); err != nil {
fmt.Errorf("%s", err)
}
return b.AddBook(book)
}
func (b *Bibliotheke) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
b.librarians <- empty{}
requests, responses := make(chan LibraryRequest), make(chan LibraryResponse)
go func() {
for req := range requests {
var resp BibliothekeResponse
b.Lock()
switch req.GetType() {
case 1:
resp = b.borrowBook(req.GetISBN())
case 2:
resp = b.returnBook(req.GetISBN())
case 3:
resp = b.bookAvailability(req.GetISBN())
}
b.Unlock()
responses <- &resp
}
<-b.librarians
close(responses)
}()
return requests, responses
}
func (b *Bibliotheke) borrowBook(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else if book.copies.available == 0 {
resp.err = fmt.Errorf("Няма наличност на книга %s", isbn)
resp.registered = book.copies.registered
} else {
book.copies.available--
b.books[isbn] = book
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
func (b *Bibliotheke) returnBook(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else if book.copies.available == book.copies.registered {
resp.err = fmt.Errorf("Всички копия са налични %s", isbn)
resp.available = book.copies.available
resp.registered = book.copies.registered
} else {
book.copies.available++
b.books[isbn] = book
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
func (b *Bibliotheke) bookAvailability(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else {
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
type BibliothekeResponse struct {
pbook *book
err error
available, registered int
}
func (br *BibliothekeResponse) GetBook() (fmt.Stringer, error) {
return br.pbook, br.err
}
func (br *BibliothekeResponse) GetAvailability() (int, int) {
return br.available, br.registered
}
// Interfaces
type Library interface {
// Добавя книга от json
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Aко са повече от 4 - връща грешка
AddBookJSON(data []byte) (int, error)
// Добавя книга от xml
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Ако са повече от 4 - връщаме грешка
AddBookXML(data []byte) (int, error)
// Ангажира свободен "библиотекар" да ни обработва заявките.
// Библиотекарите са фиксиран брой - подават се като параметър на NewLibrary
// Блокира ако всички библиотекари са заети.
// Връщат се два канала:
// първият е само за писане - по него ще изпращаме заявките
// вторият е само за четене - по него ще получаваме отговорите.
// Ако затворим канала със заявките - освобождаваме библиотекаря.
Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
}
type LibraryRequest interface {
// Тип на заявката:
// 1 - Borrow book
// 2 - Return book
// 3 - Get availability information about book
GetType() int
// Връща isbn на книгата, за която се отнася Request-a
GetISBN() string
}
type LibraryResponse interface {
// Ако книгата съществува/налична е - обект имплементиращ Stringer (повече информация по-долу)
// Aко книгата не съществува първият резултат е nil.
// Връща се и подобаващa грешка (виж по-долу) - ако такава е възникнала.
// Когато се е резултат на заявка от тип 2 (Return book) - не е нужно да я закачаме към отговора.
GetBook() (fmt.Stringer, error)
// available - Колко наличности от книгата имаме останали след изпълнението на заявката.
// Тоест, ако сме имали 3 копия от Х и това е отговор на Take заявка - тук ще има 2.
// registered - Колко копия от тази книга има регистрирани в библиотеката (макс 4).
GetAvailability() (available int, registered int)
}

Лог от изпълнението

PASS
ok  	_/tmp/d20151207-5667-1cofour	0.003s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.003s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.004s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.004s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.003s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.003s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.004s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.004s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.003s
PASS
ok  	_/tmp/d20151207-5667-1cofour	0.003s

История (3 версии и 3 коментара)

Даниел обнови решението на 01.12.2015 20:47 (преди над 2 години)

+package main
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "fmt"
+)
+
+type empty struct{}
+type semaphore chan empty
+
+type book struct {
+ ISBN string `xml:"isbn,attr"`
+ Title string `xml:"title"`
+ Genre string `xml:"genre"`
+ Author struct {
+ First_name string `xml:"first_name"`
+ Last_name string `xml:"last_name"`
+ } `xml:"author"`
+ copies struct {
+ available, registered int
+ }
+}
+
+func (b *book) String() string {
+ return "[" + b.ISBN + "] " + b.Title + " от " +
+ b.Author.First_name + " " + b.Author.Last_name
+}
+
+type Bibliotheke struct {
+ librarians semaphore
+ books map[string]book
+}
+
+func NewLibrary(librarians int) Library {
+ var b *Bibliotheke = new(Bibliotheke)
+ b.librarians = make(semaphore, librarians)
+ b.books = make(map[string]book)
+ return b
+}
+
+func (b *Bibliotheke) AddBook(book book) (int, error) {
+ if _, ok := b.books[book.ISBN]; ok {
+ book.copies = b.books[book.ISBN].copies
+ }
+
+ if book.copies.registered == 4 {
+ return book.copies.registered, fmt.Errorf("Има 4 копия на книга %s", book.ISBN)
+ }
+
+ book.copies.registered += 1
+ book.copies.available += 1
+
+ b.books[book.ISBN] = book
+
+ return book.copies.registered, nil
+
+}
+
+func (b *Bibliotheke) AddBookJSON(Data []byte) (int, error) {
+ var book book
+
+ if err := json.Unmarshal(Data, &book); err != nil {
+ fmt.Errorf("%s", err)
+ }
+ return b.AddBook(book)
+}
+
+func (b *Bibliotheke) AddBookXML(Data []byte) (int, error) {
+ var book book
+
+ if err := xml.Unmarshal(Data, &book); err != nil {
+ fmt.Errorf("%s", err)
+ }
+
+ return b.AddBook(book)
+}
+
+func (b *Bibliotheke) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+ b.librarians <- empty{}
+ requests, responses := make(chan LibraryRequest), make(chan LibraryResponse)
+
+ go func() {
+ for req := range requests {
+ var resp BibliothekeResponse
+
+ switch req.GetType() {
+ case 1:
+ resp = b.borrowBook(req.GetISBN())
+ case 2:
+ resp = b.returnBook(req.GetISBN())
+ case 3:
+ resp = b.bookAvailability(req.GetISBN())
+ }
+ responses <- &resp
+ }
+ <-b.librarians
+ close(responses)
+ }()
+
+ return requests, responses
+}
+
+type BibliothekeResponse struct {
+ pbook *book
+ err error
+ available, registered int
+}
+
+func (br *BibliothekeResponse) GetBook() (fmt.Stringer, error) {
+ return br.pbook, br.err
+}
+
+func (br *BibliothekeResponse) GetAvailability() (int, int) {
+ return br.available, br.registered
+}
+
+func (b *Bibliotheke) borrowBook(isbn string) (resp BibliothekeResponse) {
+ if book, ok := b.books[isbn]; !ok {
+ resp.err = fmt.Errorf("Непозната книга %s", isbn)
+ } else if book.copies.available == 0 {
+ resp.err = fmt.Errorf("Няма наличност на книга %s", isbn)
+ resp.registered = book.copies.registered
+ } else {
+ book.copies.available--
+ b.books[isbn] = book
+
+ resp.pbook = &book
+ resp.available = book.copies.available
+ resp.registered = book.copies.registered
+ }
+
+ return resp
+}
+
+func (b *Bibliotheke) returnBook(isbn string) (resp BibliothekeResponse) {
+ if book, ok := b.books[isbn]; !ok {
+ resp.err = fmt.Errorf("Непозната книга %s", isbn)
+ } else if book.copies.available == book.copies.registered {
+ resp.err = fmt.Errorf("Всички копия са налични %s", isbn)
+ resp.available = book.copies.available
+ resp.registered = book.copies.registered
+ } else {
+ book.copies.available++
+ b.books[isbn] = book
+
+ resp.pbook = &book
+ resp.available = book.copies.available
+ resp.registered = book.copies.registered
+ }
+
+ return resp
+}
+
+func (b *Bibliotheke) bookAvailability(isbn string) (resp BibliothekeResponse) {
+ if book, ok := b.books[isbn]; !ok {
+ resp.err = fmt.Errorf("Непозната книга %s", isbn)
+ } else {
+ resp.pbook = &book
+ resp.available = book.copies.available
+ resp.registered = book.copies.registered
+ }
+
+ return resp
+}
+
+// Interfaces
+type Library interface {
+
+ // Добавя книга от json
+ // Oтговаря с общия брой копия в библиотеката (не само наличните).
+ // Aко са повече от 4 - връща грешка
+ AddBookJSON(data []byte) (int, error)
+
+ // Добавя книга от xml
+ // Oтговаря с общия брой копия в библиотеката (не само наличните).
+ // Ако са повече от 4 - връщаме грешка
+ AddBookXML(data []byte) (int, error)
+
+ // Ангажира свободен "библиотекар" да ни обработва заявките.
+ // Библиотекарите са фиксиран брой - подават се като параметър на NewLibrary
+ // Блокира ако всички библиотекари са заети.
+ // Връщат се два канала:
+ // първият е само за писане - по него ще изпращаме заявките
+ // вторият е само за четене - по него ще получаваме отговорите.
+ // Ако затворим канала със заявките - освобождаваме библиотекаря.
+ Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
+}
+
+type LibraryRequest interface {
+ // Тип на заявката:
+ // 1 - Borrow book
+ // 2 - Return book
+ // 3 - Get availability information about book
+ GetType() int
+
+ // Връща isbn на книгата, за която се отнася Request-a
+ GetISBN() string
+}
+
+type LibraryResponse interface {
+ // Ако книгата съществува/налична е - обект имплементиращ Stringer (повече информация по-долу)
+ // Aко книгата не съществува първият резултат е nil.
+ // Връща се и подобаващa грешка (виж по-долу) - ако такава е възникнала.
+ // Когато се е резултат на заявка от тип 2 (Return book) - не е нужно да я закачаме към отговора.
+ GetBook() (fmt.Stringer, error)
+
+ // available - Колко наличности от книгата имаме останали след изпълнението на заявката.
+ // Тоест, ако сме имали 3 копия от Х и това е отговор на Take заявка - тук ще има 2.
+ // registered - Колко копия от тази книга има регистрирани в библиотеката (макс 4).
+ GetAvailability() (available int, registered int)
+}

Даниел обнови решението на 04.12.2015 15:12 (преди над 2 години)

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
+ "sync"
)
type empty struct{}
type semaphore chan empty
type book struct {
ISBN string `xml:"isbn,attr"`
Title string `xml:"title"`
Genre string `xml:"genre"`
Author struct {
First_name string `xml:"first_name"`
Last_name string `xml:"last_name"`
} `xml:"author"`
copies struct {
available, registered int
}
}
func (b *book) String() string {
return "[" + b.ISBN + "] " + b.Title + " от " +
b.Author.First_name + " " + b.Author.Last_name
}
type Bibliotheke struct {
librarians semaphore
books map[string]book
+ mutex sync.Mutex
}
func NewLibrary(librarians int) Library {
var b *Bibliotheke = new(Bibliotheke)
b.librarians = make(semaphore, librarians)
b.books = make(map[string]book)
return b
}
func (b *Bibliotheke) AddBook(book book) (int, error) {
+ b.mutex.Lock()
+ defer b.mutex.Unlock()
+
if _, ok := b.books[book.ISBN]; ok {
book.copies = b.books[book.ISBN].copies
}
if book.copies.registered == 4 {
return book.copies.registered, fmt.Errorf("Има 4 копия на книга %s", book.ISBN)
}
book.copies.registered += 1
book.copies.available += 1
b.books[book.ISBN] = book
return book.copies.registered, nil
}
func (b *Bibliotheke) AddBookJSON(Data []byte) (int, error) {
var book book
if err := json.Unmarshal(Data, &book); err != nil {
fmt.Errorf("%s", err)
}
return b.AddBook(book)
}
func (b *Bibliotheke) AddBookXML(Data []byte) (int, error) {
var book book
if err := xml.Unmarshal(Data, &book); err != nil {
fmt.Errorf("%s", err)
}
return b.AddBook(book)
}
func (b *Bibliotheke) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
b.librarians <- empty{}
requests, responses := make(chan LibraryRequest), make(chan LibraryResponse)
go func() {
for req := range requests {
var resp BibliothekeResponse
+ b.mutex.Lock()
switch req.GetType() {
case 1:
resp = b.borrowBook(req.GetISBN())
case 2:
resp = b.returnBook(req.GetISBN())
case 3:
resp = b.bookAvailability(req.GetISBN())
}
responses <- &resp
+ b.mutex.Unlock()
}
<-b.librarians
close(responses)
}()
return requests, responses
}
type BibliothekeResponse struct {
pbook *book
err error
available, registered int
}
func (br *BibliothekeResponse) GetBook() (fmt.Stringer, error) {
return br.pbook, br.err
}
func (br *BibliothekeResponse) GetAvailability() (int, int) {
return br.available, br.registered
}
func (b *Bibliotheke) borrowBook(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else if book.copies.available == 0 {
resp.err = fmt.Errorf("Няма наличност на книга %s", isbn)
resp.registered = book.copies.registered
} else {
book.copies.available--
b.books[isbn] = book
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
func (b *Bibliotheke) returnBook(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else if book.copies.available == book.copies.registered {
resp.err = fmt.Errorf("Всички копия са налични %s", isbn)
resp.available = book.copies.available
resp.registered = book.copies.registered
} else {
book.copies.available++
b.books[isbn] = book
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
func (b *Bibliotheke) bookAvailability(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else {
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
// Interfaces
type Library interface {
// Добавя книга от json
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Aко са повече от 4 - връща грешка
AddBookJSON(data []byte) (int, error)
// Добавя книга от xml
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Ако са повече от 4 - връщаме грешка
AddBookXML(data []byte) (int, error)
// Ангажира свободен "библиотекар" да ни обработва заявките.
// Библиотекарите са фиксиран брой - подават се като параметър на NewLibrary
// Блокира ако всички библиотекари са заети.
// Връщат се два канала:
// първият е само за писане - по него ще изпращаме заявките
// вторият е само за четене - по него ще получаваме отговорите.
// Ако затворим канала със заявките - освобождаваме библиотекаря.
Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
}
type LibraryRequest interface {
// Тип на заявката:
// 1 - Borrow book
// 2 - Return book
// 3 - Get availability information about book
GetType() int
// Връща isbn на книгата, за която се отнася Request-a
GetISBN() string
}
type LibraryResponse interface {
// Ако книгата съществува/налична е - обект имплементиращ Stringer (повече информация по-долу)
// Aко книгата не съществува първият резултат е nil.
// Връща се и подобаващa грешка (виж по-долу) - ако такава е възникнала.
// Когато се е резултат на заявка от тип 2 (Return book) - не е нужно да я закачаме към отговора.
GetBook() (fmt.Stringer, error)
// available - Колко наличности от книгата имаме останали след изпълнението на заявката.
// Тоест, ако сме имали 3 копия от Х и това е отговор на Take заявка - тук ще има 2.
// registered - Колко копия от тази книга има регистрирани в библиотеката (макс 4).
GetAvailability() (available int, registered int)
}

Даниел обнови решението на 04.12.2015 15:36 (преди над 2 години)

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"sync"
)
type empty struct{}
type semaphore chan empty
type book struct {
ISBN string `xml:"isbn,attr"`
Title string `xml:"title"`
Genre string `xml:"genre"`
Author struct {
First_name string `xml:"first_name"`
Last_name string `xml:"last_name"`
} `xml:"author"`
copies struct {
available, registered int
}
}
func (b *book) String() string {
return "[" + b.ISBN + "] " + b.Title + " от " +
b.Author.First_name + " " + b.Author.Last_name
}
type Bibliotheke struct {
librarians semaphore
books map[string]book
- mutex sync.Mutex
+ sync.Mutex
}
func NewLibrary(librarians int) Library {
var b *Bibliotheke = new(Bibliotheke)
+
b.librarians = make(semaphore, librarians)
- b.books = make(map[string]book)
+ b.books = map[string]book{}
+
return b
}
func (b *Bibliotheke) AddBook(book book) (int, error) {
- b.mutex.Lock()
- defer b.mutex.Unlock()
+ b.Lock()
+ defer b.Unlock()
if _, ok := b.books[book.ISBN]; ok {
book.copies = b.books[book.ISBN].copies
}
if book.copies.registered == 4 {
return book.copies.registered, fmt.Errorf("Има 4 копия на книга %s", book.ISBN)
}
book.copies.registered += 1
book.copies.available += 1
b.books[book.ISBN] = book
return book.copies.registered, nil
-
}
func (b *Bibliotheke) AddBookJSON(Data []byte) (int, error) {
var book book
if err := json.Unmarshal(Data, &book); err != nil {
fmt.Errorf("%s", err)
}
return b.AddBook(book)
}
func (b *Bibliotheke) AddBookXML(Data []byte) (int, error) {
var book book
if err := xml.Unmarshal(Data, &book); err != nil {
fmt.Errorf("%s", err)
}
return b.AddBook(book)
}
func (b *Bibliotheke) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
b.librarians <- empty{}
requests, responses := make(chan LibraryRequest), make(chan LibraryResponse)
go func() {
for req := range requests {
var resp BibliothekeResponse
- b.mutex.Lock()
+ b.Lock()
switch req.GetType() {
case 1:
resp = b.borrowBook(req.GetISBN())
case 2:
resp = b.returnBook(req.GetISBN())
case 3:
resp = b.bookAvailability(req.GetISBN())
}
+ b.Unlock()
responses <- &resp
- b.mutex.Unlock()
}
<-b.librarians
close(responses)
}()
return requests, responses
}
-type BibliothekeResponse struct {
- pbook *book
- err error
- available, registered int
-}
-
-func (br *BibliothekeResponse) GetBook() (fmt.Stringer, error) {
- return br.pbook, br.err
-}
-
-func (br *BibliothekeResponse) GetAvailability() (int, int) {
- return br.available, br.registered
-}
-
func (b *Bibliotheke) borrowBook(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else if book.copies.available == 0 {
resp.err = fmt.Errorf("Няма наличност на книга %s", isbn)
resp.registered = book.copies.registered
} else {
book.copies.available--
+
b.books[isbn] = book
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
func (b *Bibliotheke) returnBook(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else if book.copies.available == book.copies.registered {
resp.err = fmt.Errorf("Всички копия са налични %s", isbn)
resp.available = book.copies.available
resp.registered = book.copies.registered
} else {
book.copies.available++
+
b.books[isbn] = book
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
}
func (b *Bibliotheke) bookAvailability(isbn string) (resp BibliothekeResponse) {
if book, ok := b.books[isbn]; !ok {
resp.err = fmt.Errorf("Непозната книга %s", isbn)
} else {
resp.pbook = &book
resp.available = book.copies.available
resp.registered = book.copies.registered
}
return resp
+}
+
+type BibliothekeResponse struct {
+ pbook *book
+ err error
+ available, registered int
+}
+
+func (br *BibliothekeResponse) GetBook() (fmt.Stringer, error) {
+ return br.pbook, br.err
+}
+
+func (br *BibliothekeResponse) GetAvailability() (int, int) {
+ return br.available, br.registered
}
// Interfaces
type Library interface {
// Добавя книга от json
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Aко са повече от 4 - връща грешка
AddBookJSON(data []byte) (int, error)
// Добавя книга от xml
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Ако са повече от 4 - връщаме грешка
AddBookXML(data []byte) (int, error)
// Ангажира свободен "библиотекар" да ни обработва заявките.
// Библиотекарите са фиксиран брой - подават се като параметър на NewLibrary
// Блокира ако всички библиотекари са заети.
// Връщат се два канала:
// първият е само за писане - по него ще изпращаме заявките
// вторият е само за четене - по него ще получаваме отговорите.
// Ако затворим канала със заявките - освобождаваме библиотекаря.
Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
}
type LibraryRequest interface {
// Тип на заявката:
// 1 - Borrow book
// 2 - Return book
// 3 - Get availability information about book
GetType() int
// Връща isbn на книгата, за която се отнася Request-a
GetISBN() string
}
type LibraryResponse interface {
// Ако книгата съществува/налична е - обект имплементиращ Stringer (повече информация по-долу)
// Aко книгата не съществува първият резултат е nil.
// Връща се и подобаващa грешка (виж по-долу) - ако такава е възникнала.
// Когато се е резултат на заявка от тип 2 (Return book) - не е нужно да я закачаме към отговора.
GetBook() (fmt.Stringer, error)
// available - Колко наличности от книгата имаме останали след изпълнението на заявката.
// Тоест, ако сме имали 3 копия от Х и това е отговор на Take заявка - тук ще има 2.
// registered - Колко копия от тази книга има регистрирани в библиотеката (макс 4).
GetAvailability() (available int, registered int)
}