Building a text editor in Go: Setting up the backend
Tags: go, javascript, html, tutorial
Published: 2019-11-10 01:46:51

Here we will be using (the programming language) Go, if you don't have it installed, you can do so from its [official website](https://golang.org). If you're also looking to learn the language on the Go (hah!), or want to brush up some of its concepts, I suggest you take a look [here](https://github.com/golang/go/wiki/Learn).

Let's start working on that backend.

For backend, we'll be using an HTTP server built in Go. So create a file named `backend.go` and add the following code to it.

```go
package main

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

func main() {

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, Editor")
    })

    log.Fatal(http.ListenAndServe(":3000", nil))

}
```

![Hold up](https://media.giphy.com/media/xULW8MYvpNOfMXfDH2/giphy.gif)

Hold up, let me explain.

## Routing
For those who don’t know, URL routing is the practice of taking a [URL](https://en.wikipedia.org/wiki/URL) pattern and mapping it to some function that does a task when a user reaches that URL. For example, if I write

```go
http.HandleFunc("/hello", doStuff)
```

and visit the '/hello' path, the function `doStuff` will be executed, simple enough.


`http.HandleFunc` does just that, registers a handler for the route whose pattern has been provided. It takes in 2 arguments, a string representing the URL pattern you want to route to, and a handler function that, in turn, takes 2 of its own arguments.

1. A copy of an `http.ResponseWriter` instance, to handle send responses from the server.

2. `*http.Request`, a pointer of the request made to the server, that contains information about the request, like [URL parameters](https://en.wikipedia.org/wiki/Query_string), [message body](https://en.wikipedia.org/wiki/HTTP_message_body), etc.

In the end, we have `log.Fatal(http.ListenAndServe(":3000", nil))`. `log.Fatal` is equivalent to printing and exiting the program, so any code you write after it will not be reachable. Here, try running this seperate program:

```go
package main

import (
	"fmt"
	"log"
)

func main() {
	log.Fatal("I use Arch btw")
	fmt.Println("Yeah nobody cares")
}
```

You'll get an output like this:
```bash
2019/11/10 03:27:26 I use Arch btw
exit status 1
```

or if you're running on [ideone](https://ideone.com), you'll get a runtime error. You can execute the line below by removing the `log.Fatal` line as well as "log" from the `import` block.

`http.ListenAndServe` finally starts the server and _listens_ for requests on the port number provided, (3000) in our case, and returns an error if there is one. In case, there is an error (or if you **press `Ctrl+c` to stop the server**), `log.Fatal` is there to stop the print the error and stop the execution. You can learn more about `http.ListenAndServe` [here](https://golang.org/pkg/net/http/#ListenAndServe).

Now run the server using
```bash
go run backend.go
```
and visit `localhost:3000` in your browser. You should see a blank page with "Hello, Editor" written. Congratulations, you have succesfully built an HTTP server in Go.

![Nice](http://giphygifs.s3.amazonaws.com/media/IUZtGhVO8hZ6w/giphy.gif)

Now go (bad pun count = 2) execute a mad king or something, then come back when you're done, we'll add some functionality.

### Creating routes and their handlers
Since we have 2 pages &#8212; `open` and `edit` &#8212; we'll create 2 separate routes and handlers for these.

```go
// backend.go

// ...

func fileOpenHandler(w http.ResponseWriter, r *http.Request) {
	// do stuff
}

func fileEditHandler(w http.ResponseWriter, r *http.Request) {
	// do stuff
}

func main() {
       // ...	

	http.HandleFunc("/file/open", fileOpenHandler)
	http.HandleFunc("/file/edit", fileEditHandler)

      // ...
}
```

If we visit these parts, nothing happens because the function bodies are empty. When we open these links, we want our server to _serve_ the HTML files we've created for these paths. Luckily there's a function for that:

[`http.ServeFile`](https://golang.org/pkg/net/http/#ServeFile).

Let's add that to our handlers, like so:

```go
// backend.go

// ...

func fileOpenHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "open.html")
}

func fileEditHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "edit.html")
}

// ...
```

That's it, now when you open `localhost:3000/file/open` or `localhost:3000/file/edit` you'll see the HTML pages you created (make sure they are in the same directory as this Go file).

Also put the handler function for the "/" into its own function and call it `homeHandler`. Here's the whole `backend.go` file:

```go
package main

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

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, Editor")
}

func fileOpenHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "open.html")
}

func fileEditHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "edit.html")
}

func main() {
	// decare routes
	http.HandleFunc("/", homeHandler)
	http.HandleFunc("/file/open", fileOpenHandler)
	http.HandleFunc("/file/edit", fileEditHandler)

	// run server
	fmt.Println("Server listening at localost:3000")
	log.Fatal(http.ListenAndServe(":3000", nil))
}
```
![I'm done](http://giphygifs.s3.amazonaws.com/media/3XiQswSmbjBiU/giphy.gif)

Until next time ...?

_Cover image by [Eduardo Higareda](https://dribbble.com/eldelentes)_