I\'m trying to request multiple URLs with multiple std::thread
. This is how my code looks so far:
fn fetch(urls: Vec<&str>) {
let
Adding the move
is the correct solution to your first problem. The second error indicates a problem in your code that was there before already, but is detected only in a later compiler stage. So what does this second error mean?
Well, a spawned thread can run forever (more precisely: as long as the main thread/the whole program runs). In your case they don't, because you block the calling thread waiting for the results from the channel. But the compiler doesn't know that. Therefore, thread::spawn()
requires the passed closure to be : 'static
which means that it doesn't reference anything that lives shorter than the whole program.
But in your case the closure has a reference to the url, a &str
. But how long does the string behind that reference actually live? Not necessarily forever! That's the problem here.
The typical solution to problems like these is to use an Arc
and wrap the owned value in it. But this is not possible here, because your function does not have access to the owned value. There are a few possible solutions for you:
Use a scoped thread API, like crossbeam offers. This API makes sure that the spawned thread doesn't outlive its parent, so you can just reference the &str
inside of your closure. I think this is actually the best solution with the only downside of pulling in a new dependency.
Change your function signature to fn fetch(urls: Vec<&'static str>)
. It works, but it limits the callers of your function as they have to provide static strings. I guess that the list of URLs is not just a list of string literals, but dynamically generated; so this is not really a solution for you.
Clone the &str
to move the resulting String
into the closure. This is not really a nice solution, though, as useless clones should be avoided. But it could be tolerable in your situation as the HTTP request will takes a whole lot longer than cloning a rather small (url) string.