How to do it...

These steps cover writing and running your application:

  1. From your Terminal or console application, create a new directory called ~/projects/go-programming-cookbook/chapter10/pool and navigate to it.
  2. Run the following command:
$ go mod init github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter10/pool

You should see a file called go.mod that contains the following content:

module github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter10/pool    
  1. Copy the tests from ~/projects/go-programming-cookbook-original/chapter10/pool, or use this as an opportunity to write some of your own code!
  2. Create a file called worker.go with the following content:
        package pool

import (
"context"
"fmt"
)

// Dispatch creates numWorker workers, returns a cancel
// function channels for adding work and responses,
// cancel must be called
func Dispatch(numWorker int) (context.CancelFunc, chan
WorkRequest, chan WorkResponse) {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
in := make(chan WorkRequest, 10)
out := make(chan WorkResponse, 10)

for i := 0; i < numWorker; i++ {
go Worker(ctx, i, in, out)
}
return cancel, in, out
}

// Worker loops forever and is part of the worker pool
func Worker(ctx context.Context, id int, in chan WorkRequest,
out chan WorkResponse) {
for {
select {
case <-ctx.Done():
return
case wr := <-in:
fmt.Printf("worker id: %d, performing %s
workn", id, wr.Op)
out <- Process(wr)
}
}
}
  1. Create a file called work.go with the following content:
        package pool

import "errors"

type op string

const (
// Hash is the bcrypt work type
Hash op = "encrypt"
// Compare is bcrypt compare work
Compare = "decrypt"
)

// WorkRequest is a worker req
type WorkRequest struct {
Op op
Text []byte
Compare []byte // optional
}

// WorkResponse is a worker resp
type WorkResponse struct {
Wr WorkRequest
Result []byte
Matched bool
Err error
}

// Process dispatches work to the worker pool channel
func Process(wr WorkRequest) WorkResponse {
switch wr.Op {
case Hash:
return hashWork(wr)
case Compare:
return compareWork(wr)
default:
return WorkResponse{Err: errors.New("unsupported
operation")}
}
}
  1. Create a file called crypto.go with the following content:
        package pool

import "golang.org/x/crypto/bcrypt"

func hashWork(wr WorkRequest) WorkResponse {
val, err := bcrypt.GenerateFromPassword(wr.Text,
bcrypt.DefaultCost)
return WorkResponse{
Result: val,
Err: err,
Wr: wr,
}
}

func compareWork(wr WorkRequest) WorkResponse {
var matched bool
err := bcrypt.CompareHashAndPassword(wr.Compare, wr.Text)
if err == nil {
matched = true
}
return WorkResponse{
Matched: matched,
Err: err,
Wr: wr,
}
}
  1. Create a new directory named example and navigate to it.
  2. Create a file named main.go with the following content:
        package main

import (
"fmt"

"github.com/PacktPublishing/
Go-Programming-Cookbook-Second-Edition/
chapter10/pool"
)

func main() {
cancel, in, out := pool.Dispatch(10)
defer cancel()

for i := 0; i < 10; i++ {
in <- pool.WorkRequest{Op: pool.Hash, Text:
[]byte(fmt.Sprintf("messages %d", i))}
}

for i := 0; i < 10; i++ {
res := <-out
if res.Err != nil {
panic(res.Err)
}
in <- pool.WorkRequest{Op: pool.Compare, Text:
res.Wr.Text, Compare: res.Result}
}

for i := 0; i < 10; i++ {
res := <-out
if res.Err != nil {
panic(res.Err)
}
fmt.Printf("string: "%s"; matched: %vn",
string(res.Wr.Text), res.Matched)
}
}
  1. Run go run main.go.
  2. You may also run the following commands:
$ go build
$ ./example

You should now see the following output:

$ go run main.go
worker id: 9, performing encrypt work
worker id: 5, performing encrypt work
worker id: 2, performing encrypt work
worker id: 8, performing encrypt work
worker id: 6, performing encrypt work
worker id: 1, performing encrypt work
worker id: 0, performing encrypt work
worker id: 4, performing encrypt work
worker id: 3, performing encrypt work
worker id: 7, performing encrypt work
worker id: 2, performing decrypt work
worker id: 6, performing decrypt work
worker id: 8, performing decrypt work
worker id: 1, performing decrypt work
worker id: 0, performing decrypt work
worker id: 9, performing decrypt work
worker id: 3, performing decrypt work
worker id: 4, performing decrypt work
worker id: 7, performing decrypt work
worker id: 5, performing decrypt work
string: "messages 9"; matched: true
string: "messages 3"; matched: true
string: "messages 4"; matched: true
string: "messages 0"; matched: true
string: "messages 1"; matched: true
string: "messages 8"; matched: true
string: "messages 5"; matched: true
string: "messages 7"; matched: true
string: "messages 2"; matched: true
string: "messages 6"; matched: true
  1. The go.mod file may be updated and the go.sum file should now be present in the top-level recipe directory.
  2. If you copied or wrote your own tests, go up one directory and run go test. Ensure that all the tests pass.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.174.168