In the Readme, you'll find likes to episodes 9 and 10, which deal with explaning and implementing the context package.
But, to answer your question very quickly: the purpose for the cancel function is to voluntarily signal to the rest of your program that one particular flow of operations (determined by you, when you design your application) is over.
You are calling it as a courtesy to some other go routines inside your program which may depend on, or act upon the same operation.
In your case, you want to read from that external endpoint some json or xml values, right ?
As far as you're concerned, the real "finish line" of that particular flow is after ioutil.ReadAll, not the ctxhttp.Do method, correct ? That's why you need to make sure you call cancel() after that one, not too early.
Due to the fact that you are calling cancel too early, as Tamás pointed out, you are not guaranteed to receive the response body, because the http internal mechanisms are not synchronous and are complex enough.
If you have some good hours to spend (take your time, to understand it correctly), dig into the source code directly. Start with
that will take you into:
and so forth...