Learn to Code via Tutorials on Repl.it!

← Back to all posts
All of the fundamentals of a web server in Go
h
Baconman321 (1096)

Yall

like Node JS right?

How about making web servers in Node JS?

Sometimes though, don't you get the obsession to make your program run faster?

I totally don't

Maybe you thought "Oh, I should use C++!"

Nah, I didn't think that

But, C++ isn't the fastest, so you thought "maybe I should use assembly >:D"!

I TOTALLY didn't think of that

However, do you really want to re-define TCP handling in assembly, or give up after trying to find out how to make the web server work in C++?

I totally didn't give up trying... oh wait... I mean... I didn't think of it? Sigh... :P

Those are the only "fast" and "high performance" languages out there though, right?

Nope!

There's also another language that aims to be both fast and simple - Go!

Ok, there are tons of other languages you can use that are fast as well, but Go is gaining popularity and is pretty nice overall.

According to wikipedia, Go is "a statically typed, compiled programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. Go is syntactically similar to C, but with memory safety, garbage collection, structural typing, and CSP-style concurrency."

Basically, Go is a fast boi.

Ok then, lets Go (LOL the Go puns, I love 'em hehehe) learn how to set up a web server in Go, shall we?

Prerequisites

You will need some basic knowledge of Go variables and functions for this. That is, unless you are going to be using the server as a server and using it to serve files and nothing else (which could be done with a HTML,CSS,JS repl soooo...)

Step 1: The step 1

Ok, hmmmm that's not so informative....
Ok I'm going to redo this..

Hmmmmm...

Oh, got it!

Ok nvm. Step 1: making a Go repl

Smash that plus button in the upper-right corner of your screen on the repl homepage!

Ok, don't actually smash it... unless you like to torture your mouse/touchpad :| .

Then, you should choose your language. Search for and click "GO". Since I have made a few Go repls it appears in my favorites, but to narrow it down just type "Go" in the search bar of your new repl language popup.

Name it to whatever you want (I'm going to name it to "fast server boiiiiiiieeeeeeee"), and then click "Create repl".

You should be redirected to your newly created repl and it should look something like this:

Now, clicking the run button you will see that it prints "Hello world".

Unless you want the attack of the simpletons as your new text adventure game, I would advise you to change your code.

If you don't, I can show you perfectly what Hello World Hell looks like:

Uhmmmmm, I'd rather go to Web Server Haven, wouldn't you?

Step 2: Writing code!

Ok, first things first.

See that import "fmt"?

We will need to import a few more things.

Let's wrap it in a parentheses block. As much as you remember adding commas between strings, Go's import doesn't need that (as long as you create a newline after each string... I think).

It's as simple as this:

package main

import (
  "fmt"
  "net/http"
  "log"
)

func main() {
  fmt.Println("Hello World")
}

Ok, that's nice and all, but it won't make us a web server yet. Plus, running it gives us an error, since Go makes sure you use your variables and packages. If you don't, well... let's just say it gets angry.

Ol' "Hulky Bulky Go" here doesn't want us to leave our dinner plate unfinished, so let's make a web server for real.

First things first, we need a handler.

You probably have done this in Node JS, so I'm pretty sure you know the concept here.

package main

import (
  "fmt"
  "net/http"
  "log"
)

func main() {
  http.HandleFunc("/",ourHandlerFunc)
}

Ok, that's a good start.

Well, it's going to work, right?

Oh wait, my undefined function sense is tingling.

Yep, we need to define ourHandlerFunc!

package main

import (
  "fmt"
  "net/http"
  "log"
)

func ourHandlerFunc(w http.ResponseWriter, r *http.Request){
  fmt.Fprintf(w, "Hello, world!")
}

func main() {
  http.HandleFunc("/",ourHandlerFunc)
}

Ok, all done with the handler func!

Now, we have to serve it!

package main

import (
  "fmt"
  "net/http"
  "log"
)

func ourHandlerFunc(w http.ResponseWriter, r *http.Request){
  fmt.Fprintf(w, "Hello, world!")
}

func main() {
  http.HandleFunc("/",ourHandlerFunc)
  log.Println("Listening on port :3000...")
  err := http.ListenAndServe(":3000",nil)
  if err != nil{
    log.Fatal(err)
  }
}

Ok, so now it's listening on port 3000!

Note that if you are to change the port number, you gotta include the ":" in the string.

Step 3: Running it!

If you are to run it, it should give "Hello, world!" in the preview of the webpage.

You did it!

How does it work though?

We make a function called "ourHandlerFunc" that takes in the response writer (what we use to write our response with) and our request.

The request handles things like the details and headers, while the writer allows us to manipulate our response back to the client.

Pretty neat, huh?

Oh wow, we are done... no?

Well, unless you want to code all of your HTML, CSS and JS inside of a string!

In addition, Go can also serve content from a file!

Step 4: Changing it to be better!

Ok, let's delete the ourHandlerFunc and the http.HandleFunc("/",ourHandlerFunc).
You should also delete the "fmt" import in your import statement unless you are going to use it elsewhere, otherwise it is going to throw you an error.

Now, make a folder called public.

This is where we keep all of your content.

It is important to keep your content inside of a folder. Otherwise Go just redirects infinitely (at least with the index.html. I found that out the hard way......)

Next, you simply add these two teeny tiny lines in to your main function:

fs := http.FileServer(http.Dir("./public"))
http.Handle("/",fs)

What is it doing?
Basically it serves the file corresponding to the name of the request in the folder it's given.

So, now you should make a folder called public, put in an index.html, and write boilerplate code for a hello world html file.

Then, run it and see the results!

Wow!

Now it can give whatever files you put in there!

Neat, huh?

Hmmm, now for one last thing.

Let's time it to see how fast it responds with the simple "Hello, world" server we made.

package main

import (
  "fmt"
  "net/http"
  "time"
  "log"
)

func ourHandlerFunc(w http.ResponseWriter, r *http.Request){
  start := time.Now();
  fmt.Fprintf(w, "Hello, there!");
  end := time.Since(start);
  fmt.Printf("Time taken to respond to %s (in microseconds): %s", r.URL,end);
}

func main() {
  http.HandleFunc("/",ourHandlerFunc);
  //This is where you put your port number. Notice that you put a ":" in front of the number as well.
  var port string = ":3000"
  log.Printf("Listening on port %s ...",port);
  http.ListenAndServe(port,nil)
}

This times the time it takes to write "Hello, there!" to the client.

If you run it, you will notice it measures it in "µs".

What is that?

"µs" is an abbreviation for microseconds, which is one thousandth of a millisecond!

Wow, Go is a fast boi after all!

Conclusion

Well, I really hope you enjoyed me rambling on about how to make a web server in Go.

There are plenty of other languages to choose from Rust or Crystal (which I heard aims to be as fast as C!), but I chose Go because it's now burned in my heart forever.

Have fun experimenting, it took me about 40 minutes to make this so I hope you enjoy it!

Please leave an upvote and a comment if you like, otherwise just tell me how I could have done better!

Bacon boi out!

Comments
hotnewtop
btfuss (177)

hello world hell...

why

btfuss (177)

@Baconman321 this is the best tutorial ive ever read

Baconman321 (1096)

@2plus2is4hoi Oh thanks!

I've done a few others as well