Solution: Resizing images
- [Instructor] So we need to convert CenterDir to run concurrently and to limit the number of goroutines by end. And there are two approaches to do it. One is that every time before you launch a goroutine, you check the current number of running goroutines and then if there are end goroutines already running, you wait until one of them terminates. The other one is to pre-launch and work your goroutines and then send jobs to them. And this is what I'm going to do but the other way is also fine. So I'll start with the request that is going to go for the worker goroutine. And basically it's going to have the source file and the destination file. And now I'm going to create my worker and it is going to get a context to know if something is done. The input channel, which is a channel of request. And we signify that this is a channel should read from and the output channel, and this is a channel it should write into off errors. And basically a worker does an infinitely, what it does is does select on the input channel. So if we get something from the input channel we need to check. If not, okay, this means that someone closed the input channel. So we return, otherwise we send to the output channel the result of calling center with r.src and r.dest. And we also need to check if the context has expired and if it does, we return. So now our worker is running, receiving from the input channel and sending arrows to the output channel. And I'm going to also create a producer. And this producer is going to send these requests into the input channel, right? So it also get the context, it'll get the in which is a channel. And this time the producer is writing to this channel and we get source files, which is a slice of strings and the destination directory, which is a string. And we need to make sure that when the producer is done, it's closing the input channel, telling basically all the worker goroutines, no more input is coming. And now for every source file in the source files, we formatted destination. So this is fmt.Sprintf of %s/%s with the destDir, destination directory and filepath.Base (src). So basically it's just going to give me the base name for the file. And now we do a select again. And this time if we manage to send into the input a request with src and dest, this is great, oops. Like this, this is great. And basically we don't need to do anything. So no operation. But if we manage to get something from the context done, we return. This means nothing is done more. By the way, when we return, we close the input channel and all the workers will get notified. And now we can go and change our center there, right? So the first part when we get the names of the file, this is fine. And now we need to create our in and out channels. So it's going to be a channel of request and this is going to be a channel of errors. And because I know how many errors are coming out and I don't want the goroutines, the workers to block when they're sending to the error channel, I'm going to use a buffer channel with len of matches. So now we have these two channels, and now for i equals zero, i smaller than n, i plus plus, I'm going to spin now a worker with the context that we have the input that matches and the destination director. The worker just gets the input and the output channels and that's it, right? Look at the worker input and output channel. So again, this is sending the work. So now the worker is ready, sorry, we didn't send the work anymore but now we can call the producer with the contacts, the input channel, the matches and the destination directory. And now we have another goroutine which is the producer that is running. Now we just need to collect the results. So we can do for range of matches which is going to replace this one. And basically what we are going to do again is select, case, err, we got something from the output channel. And if it's not nil, we are going to return it. And if the context expires, we are going to return and the context has an error. So this is the error that we're going to return. So this is the for. And finally we're going to return nil, meaning everything went well. Let's test the code. And seems like it works.