Application Entry Point in Go
The application entry point is placed under the cmd directory, which contains executable binaries. A main package is created to initialize and start the blog application.
Main Function Structure
The main function creates a background context, loads configuration, and calls a separate run function. Errors during initialization or execution cause the application to exit with a non-zero status code.
Testable Run Function Design
The run function accepts context and configuration, returning an error to enable testing. This separation improves testability and ensures the application can be validated in different environments.
HTTP Server Setup
Inside run, a router is initialized and passed to an http.Server instance. The server is configured with an address from the configuration, request handler, read/write timeouts, and a shared base context.
Server Execution and Logging
The server logs a startup message and begins listening using ListenAndServe. The returned error is propagated to allow proper handling at the entry point.
Running and Verifying the Application
The application is executed using go run, sourcing environment variables beforehand. The server starts on localhost:8080, confirming that routing and basic functionality work, though database integration is still pending.
Next Steps: Database Integration
While the blog application runs, it lacks persistent storage. The next step is integrating PostgreSQL and covering related database concepts to fully develop the system.
So far, we have set up models, views, controllers, we have configured a router, we have made a way to configure the environment we are operating in, but we still have one critical question left, and that is how do we actually start and run the application?
In Go projects, you typically have an entry point that lives under a CMD that is short for command directory, which is where we put the binaries of our project, the actual programs that we run.
So for our blog, this means that we're going to create this command slash app slash main, so we have the entry point to our app in this place.
And this is going to contain files.
For now, at least two elements.
It's going to contain the main function that we have to have there, and then it's going to contain a run function.
But let me create the main function first, and then I'm going to explain the run function after.
So we're going to do func main.
We're going to create our context.
Set it in the background.
Then we're going to grab our configuration, calling .new.
If there is an error, we are not going to return an error.
We're going to say OS exit with status 1, and then we're going to say if error equals to run.
And this function that we haven't created is going to say accept context and the configuration.
And if there is no error, or if there is an error, sorry, we're going to say OS exit 1.
And if there is no error, we're going to say OK.
And if there is no error, we're going to say OK.
And if there is no error, we're going to say OK.
And if there is no error, we're going to say OK.
Now, what this does is that we can actually create tests for our entry point for running the application.
So we know that whenever we make changes that the application can run because this is the only entry point.
And by having a run function that returns an error, we can create tests around this.
And this is really, really nice when you start to get to larger environments.
We have the option to pre-configure a test for a test environment that we can actually validate that our app compiles and runs.
Now, this run function here is going to contain a few things.
So let me just flesh out what the signature is going to look like.
So we're going to have the context right.
We're going to have the config, and then we're going to return the error.
And that's it.
And that's it.
And then inside of here, you're simply going to say router equals router new.
And then we're going to create a server variable or SRV, which is just short for server.
Then we're going to use an HTTP.server from the standard library.
And in here, we're going to have an adder or an address, which we can now grab from our config, the get TCP adder.
We're going to have a handler.
Which is simply just going to be the router.
And then the field called handler, which is technically just an echo instance.
But the naming here makes it make sense, right?
Makes it make sense.
Finally, we're going to add our read timeout, which is just going to be one times one.
Let's just go for a minute.
And then our write timeout.
I misspelled timeout here.
Just a screw for two minutes.
So that if an operation takes a read or write operation takes longer than this,
we will then return an error that a timeout has occurred and then accept new request again.
So we don't hang in the event of something going wrong.
Finally, we're going to set a base context.
It's going to be a func.
They're going to say net listener.
It's going to return context.
And it's just going to return the context that we are passing.
So we actually use the same context for everything.
And then underneath here, we're going to say slug info.
Starting server.
And we're going to say error.
And then serve.
And then we're going to say error.
Finally, we're going to say return serve.
And then we're going to say listen and serve.
With this, we now have a proper and testable interpersonal application.
And we can now run it by saying go run command app main.go.
But nothing great is really going to happen yet.
We haven't styled it.
We haven't set up a proper database.
So we're not really restoring or retrieving any proper data.
But if we were to say source.env,
and I say go run command app main.go,
we can see that it now starts on localhost:8080.
And if I just quickly jump into our browser here.
And then go to localhost:8080.
We can see we have a sample article readme and another sample article readme.
We can click the readme links to see the article.
So our app is working.
Our blog is technically working.
But.
We still need a database.
And then we can actually start to properly build out this application.
So in the next module, we're going to focus on Postgres,
setting up a database,
and talking through a bunch of Postgres-specific concepts.