All right, let's look at another important concept in the go programming language, and that is channels
and channels are unique to go, or at least as far as I know, I've never seen them anywhere else.
And channels are not that difficult, but they are incredibly useful.
They are a means of sending information from one part of your program to another part of your program
very easily.
So we've so far, we've seen things we're going to have here is an empty package and our empty program.
I have two packages of it saves me the last time I have Helper's, which is empty.
It has nothing and I have my main package, which just has an empty main function.
Now we've seen how to pass things around before.
For example, I can say func print text and it takes a string as an argument and it returns nothing.
And all it does is log the print line and then the string that I've passed it and then I can call that
function from up here so I could say print text.
Hi.
So what I'm doing is passing information from my main function to my print text function, and that's
one way of passing information.
We also saw how you could do it using pointers and I'm not going to go through that again.
You can just watch that lecture again if you wish to.
Well, there's a third way of doing it, and that way is creating a channel.
So I'm going to get rid of this function and I'm going to get rid of this call to that function.
And we're back to an empty manuchehr or main function.
So now I'm going to create a channel and you create channels in a way that's very similar to the way
that we created maps.
He used the make keyword.
So I'll call this and into Champ, it's going to be a channel of its and it is created by saying make
channel it.
And all that says is I'm creating a channel, a place to send information which will be received in
one or more places in my program, and that channel can only hold it.
That's all that it can hold.
So what do I do with that?
Well, it's pretty straightforward.
Let's create another function and I'll do it above the main function.
And that's going to be called func calculate value.
And it's going to take an argument of its channel and it's a type channel of it and it doesn't return
anything.
And what does this do?
Well, in here I want to generate a random number and then I want to do something with that random number.
And just for fun, I'm going to create my random number function over here and my helper function.
So let's create a random number and it's not as easy as you might think.
We can do it like this.
We could say func random number that takes an argument and we want to create a random number from a
pool of some size and that will be an entry and it will return the random number we calculate.
So what do we do?
We can say, first of all, we could say value.
Is assigned and we're going to call a built in package.
OK, we're going to call it built in package from the go language and it is called math.
So we will use Rande and we're going to choose the correct package here.
We want Rande and the function we want is IMT and there it is Matheran.
And it's going to take an argument.
And the argument it has to take is how big is the pool.
So that will be m what we passed as a parameter.
So now we've created around a number and we just want to return that.
That's all that we want to do so we can say return value.
OK, so apparently we've created a random number.
Let's go back to our main program and let's get that random number in our calculate function.
So random number, which is just a variable name, is assigned the value of and I want to call random
number Helper's random number and I want to call it from some pool.
Now, I could put 10 in here if I want to, but I'm going to use a constant const and I'll call it num
pool
and I'll make it equal to ten and then I'll just use that constant down here just because I can.
So that would be no pool and we want to return that.
Do we want to return it?
No, we want to use our channel because what we've passed it is a channel.
So I'm going to now pass that random number that I've just generated into my channel.
And I do that using a very simple syntax int channel the channel name, and I'm going to pass it.
Random number.
OK, so now down here, I've created my main function.
I've created that main channel and I want to close it once this check, once this program or this function
is finished executing.
Now we're in our main function.
So technically I don't have to close it because the program will exit as soon as I'm done.
But it's good to get in the habit of doing this.
Defer clothes and my enchante, now that Dhafir is a word we haven't seen yet, and it's when you're
going to be using regularly in our programming as we go through this course.
And all first says is whatever comes after this keyword, defer, execute that as soon as the current
function is done.
Now that becomes useful because in situations where, for example, I open a file or I open a connection
to the database, I don't want to leave those things open forever because every time you open a file
on your file system, you're using one of a limited number of files that you can have open at the same
time.
And if you leave them all open every time you create a file or open a file for reading, for example,
eventually you're going to run out of handles for the files.
So you want to close them after you open them.
And the same is true of database connections.
You can have a limited number of database connections open at a given time, and when you run out,
bad things happen and closing them after the function is finished, after you're finished using that
function is just good practice.
In fact, it's critical you have to do it.
So here I don't want to have I can again, I can have a limited number of channels open.
It's a big number, but if the program runs for seven months or 12 years or whatever, eventually you're
going to run out of them.
So I close them when I'm done with it.
And here I'm just going to do that because it's good practice.
Now we are going to call our calculate values, but I'm going to do it in a way that you haven't seen
yet, and I'm going to do it by sending it off as a concurrent operation.
I'm going to do it by running this routine in its own go routine.
So it runs.
And the nice thing about this is go routines run at the same time.
So if I need to do a thousand things, I don't have to do them one at a time.
I can fire off a thousand go routines, all of which run at the same time.
Thousands, a big number.
But you get the idea and you do that simply by saying go in front of the call to the function that you
want to call.
And that turns into a go routine.
And I'm going to now call calculate value and I'm going to pass my channel into.
There I have done that and now I need to listen for the response to that channel.
So up here I passed Evalu into the channel down here, I want to get a value from the channel and I
do that.
It's a really straightforward syntax.
I'm going to say my no, whatever it is, I'll just call it num is assigned the value of whatever comes
from enchante.
And then I'll print it out, log print online.
And no, all right, so that should work.
Now let's see what happens when we run this.
I'm going to open my terminal window and I'm going to clear the screen and I'm going to just run the
program.
Go run, Mingo.
I got one out of my pool of ten.
Let's run it again.
Go, run, go.
I got one.
Go, run, go.
I got one.
Which doesn't seem terribly random.
And in fact, it's not.
And it's not for a very simple reason.
It would be random if this program was called would be pseudo random if the program wasn't exciting
every time it was called.
But in my helper's file, if I roll over inten, you actually see a little comment here sitting with
the same value results in the same random sequence.
Each run for different numbers, seed with the different values such as time.
Now Unix and A. which yields a constantly changing number.
Aha.
That's all we have to do to get a random number here.
So I need to see it and I see that by saying rande dot seed.
And what I want to do is exactly what they told me inside of those parameters.
I'll go with time dot now, which is the current time now, which is the current time, and then I want
to get the Unix Nano and that gives me a different number every time I run this.
So if we go back to our main program and we clear the screen and we run it again, this time I got two
and I run it again and this time I got three and this time I get six.
So now it is more random.
So what it's returning is a random number between zero and my number.
So if I make this number pool a thousand and clear the screen and run it again, this time I got 50,
this time I got 412 730.
But the important thing here is not the fact that we're getting random numbers, it's where we're getting
that value from.
So let's go through this.
I have a main package.
I have my main function that runs first.
Actually, it declares this constant first, but this runs first.
And then I create a channel, a channel that can only hold INTs if I try to pass a string or a float
or a date or something else in there.
It's not going to work.
You can't even compile the program.
It can only take it.
Then I say when I'm finished running close this channel, which is good practice, not necessarily in
the main function, but I'm going to do it anyway.
And in later situations where we use this main function to initialize channels and then the main function
continues to run for a long time, that's definitely critical.
So do that get in a good habit of closing things that need to be closed and we'll be going through a
number of things that need to be closed.
So I create the channel, I defer the clothes, and then I say fire off a new go routine, run this
by itself and its own routine and hand it the channel.
Great.
So I then this fires off up here.
This as a go routine and that takes a channel is an argument and I generate a random number and then
I just say, push that back into the channel you've just given me down here.
I'm listening for that channel and when I get a value from it, it's passed into this variable num and
then I just print it out.
So that's just a really useful way of passing information from one package to another package or one
part of your program to another part of your program.
Incredibly powerful and very, very useful when you have more than one package in your program, which
we're going to have.
So those are channels and we'll be using them regularly as time goes on.