Package main and Entry Point
In Go, package main defines an executable program, and func main serves as the entry point. When running a program, Go looks for this function to start execution, either from a specific file or an entire directory.
Running Multiple Files in a Directory
When multiple files belong to the same package, running a single file may cause unresolved references. Executing go run . runs all files in the directory, allowing functions across those files to be used together.
Creating and Using Custom Packages
Code can be organized into separate directories as distinct packages to improve structure and reuse. Moving a file into a new directory changes its package scope, requiring it to be imported before use in other packages.
Exported vs. Unexported Identifiers
Go controls visibility through naming conventions rather than keywords. Identifiers starting with a lowercase letter are private to the package, while uppercase names are exported and accessible from other packages.
Package Design Best Practices
Only expose what is necessary to avoid tight coupling and unintended dependencies. A recommended approach is to keep identifiers private by default and make them public only when required.
Go Modules and go.mod
Every Go project uses a go.mod file to define the module name and manage dependencies. It is initialized with go mod init <module-name>, enabling proper package imports and dependency tracking.
You might have noticed that we have been operating inside files that said package main at the top
and had a func main inside of them. We also have been using lowercase and camel case
naming for all variables or structs and functions. These all have a special meaning in Go. If you
start by looking at packages, in Go package main is a special package that acts as an entry point
for our programs with func main being the one that kick everything off. This means that when
we run a Go program we can point it to either a main.go file or to a directory that has a main.go
file inside of it. Go will then look for a func main and start the program from this point.
So if we were to say something like
fmt print hello world
and then go and say go run main.go in the terminal this would then print out hello world.
Okay so let's try and add another file here and let's create a file called output.go this is also
in package main and let's say it has a function called print hello world that just says fmt
print hello world
give that a save and now we can go in our main.go file and say print
hello world give that a save and now again if we run go run main.go we will see that
we get an error because it only knows about one file if we point it directly to the main.go file.
What we need to do is we need to run it by pointing it to the directory.
So instead if we are to go out into the terminal we need to say go run and then a dot if we're in
the in the current directory and we will now then see that it prints out hello world in terminal
once again. But having everything in the same directory can quickly become hard to manage.
Also we might have code that we don't necessarily want to be used in specific places.
To solve this let's create a new directory called
output.go.
This directory is called output.go.
And we need to create a new directory called output.go.
And we need to create a new directory called output.go.
And we need to create a new directory called output.go.
And we need to create a new directory called output.go.
And we need to create a new directory called output.go.
And we need to create a new directory called output.go.
And we need to create a new directory called output.go.
And we need to create a new directory called output.go.
And inside here we're going to move the output.go file.
So let me just delete it.
And then we jump in here and say output.go in package output.
And then inside here we can now specify print hello world once more.
And we're just going to say hello world again.
Great.
However, if we now go into our main.go file, you will see that we have an undefined.
It doesn't know about this print hello world function anymore.
And that is because we have moved that function into another package.
Now, how can we expose this print hello world function?
Well, the way Go deals with public and private variables,
or elements, is through naming and not through keywords, as you see in other languages.
If something is lowercase, it's a private element and can only be used within the packet
that it was created.
To expose this print hello world function from our outputs package,
we will need to go inside outputs once again, and then uppercase it.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
Now this function is exposed from the output package.
And we can go inside our main.go file here and say output.
There we go.
And now we have access to this print hello world function.
Notice how we also have an import statement underneath the package main,
which I will explain in just a minute where this comes from.
But essentially, this is how we can group our code into packages that have semantic meaning
and be reused, but also only reuse what we want to share from certain packages.
It's always important to think about what you expose from a package
as other packages can come to rely on it.
A good rule of thumb is to be liberal in what you accept,
but conservative in what you return.
And always start your variables and structs and functions as private and then make them public.
As you need.
Finally, we need to talk about Go modules.
If you have checked the repository where all of these code examples are,
you might have noticed a go.mod file.
This file is required for every Go project and is used to track our project
and the project's dependencies.
I have already created this file and given it the project name masterful stack golang.
But to create this file, we simply go into an empty document.
And then we say go mod init and then the name of our package.
In this case, it will be the full stack full or master dash full stack dash golang,
which will then create a go.mod file and we can begin working.
This name masterful stack golang is the same as we saw earlier when we imported the outputs package.
In the next module, we will start laying the foundations for the app completely from scratch,
including initializing this module.
So you will see how everything works and how it looks starting our new Go.mod from scratch.