Write content to disk in separate goroutines

Move the `WriteToDisk()` method from the `CrawlerMessageItem` interface
to run as part of the main workflow in `workflow.go` because writing is
a separate concern to crawling.

Update the tests accordingly and improve them so that we check for
existence of the file created on disk.

Use two goroutines for symmetry with `CrawlURL()`. Note that we reject
the message without requeueing it as a failure to write to disk is
likely to require some manual intervention and I don't think it's wise
for us to retry.
Explicitly declare channels for readability

Declare the variables we use as
channels before they are used to improve readability.

When I first looked at this code, being new to Go, it took me a moment
to realise that `acknowledge`, `crawlItems` and `extract` are in fact
channels. By using `var` instead of the `:=` shortcut, it should be
clearer what these are.

I also considered (credit to @dancarley) creating a custom type such as:
```go
type itemChan <-chan *CrawlerMessageItem
```

However, I think using this and replacing all instances of `<-chan
*CrawlerMessageItem` in the codebase, while reducing duplication, would
obscure its meaning.
Rename channels to make their intent clearer