I created a web server with Go
language and deployed it Google Cloud Run inside a Docker
container.
You can try here the bingo sheet generator app .
Why Go instead Python for web server
Most of my programming experience is from Python
. This is the reason I started the web app project with FastAPI
framework.
As the name suggest, FastAPI is fast. Have to admit, I am not sure if it the core code is written in C or other high performance language.
In general, Go language is be much faster programming language than Python. This made me interested giving Go a try in a real case.
Go web server folder structure
app/
main.go
public/
index.html
Dockerfile
docker-init.sh
Example of Go web server code
The app returns user a simple one page HTML file with Javascript functionality. So, there were not much requirements for the Go web server.
Here is an example of main.go
file:
package main
import (
"net/http"
"fmt"
"log"
"encoding/json"
)
func printHandler(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "Hello world!")
}
func apiHandler(w http.ResponseWriter, r *http.Request){
type Profile struct {
country string
cities []string
}
profile := Profile{"Finland", []string{"Helsinki", "Tampere", "Turku"}}
response, err := json.Marshal(profile)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
w.Write(response)
}
func main() {
fileServerHandler := http.FileServer(http.Dir("./app/public"))
http.Handle("/", fileServerHandler)
http.HandleFunc("/hello", printHandler)
http.HandleFunc("/api", apiHandler)
fmt.Printf("Starting server at port 1000\n")
if err := http.ListenAndServe(":1000", nil); err != nil {
log.Fatal(err)
}
}
This creates three endpoints:
/
returns HTML files frompublic
folder/hello
printsHello world!
/api
prints{"country":"Finland","cities":["Helsinki", "Tampere", "Turku"]}
UI for the app with Go web server
The Go app serves anything in the public
folder. If you go to http://example.com/
, it returns file from public/index.html
.
UI can be implemented by any framework. Or you can use plain HTML and Javascript. I injected React
elements to the main element in index.html
.
All app logic is in Javascript. Thus, the app does not need to contact the Go web server after the first load.
Dockerfile for Go web server
This is the Docker
configuration for Dockerfile
:
FROM golang:1.19
SHELL ["/bin/bash", "-c"]
WORKDIR /workdir
CMD mkdir bin
COPY ./docker-init.sh ./docker-init.sh
COPY ./app ./app
RUN go mod init mycompany/mymodule
RUN go mod tidy
RUN go get -d ./...
EXPOSE 1000
ENTRYPOINT ["/workdir/docker-init.sh"]
Dockerfile will execute docker-init.sh
to use different commands for local development and Cloud Run deployment. go run
is suitable for development environment to instantly apply to changes. go build
on the other hand creates an executable file suitable for production environment Google Cloud.
#!/bin/bash
echo $ENV_NAME
if [ $ENV_NAME = "local" ]; then
echo "Docker entrypoint: Is local"
go run /workdir/app/main.go
else
echo "Docker entrypoint: Not local"
GOOS=linux go build -o ./bin/linux_app ./app/main.go
./bin/linux_app
fi
Conclusion of the Go web server
Go web server would work just fine without Docker. I just find Docker easy for any development project to make all environments similar. Also, Google Cloud Run supports Docker containers out of the box.
In this scenario FastAPI vs Go server did not make any practical difference. Google Cloud cold start caused much more delay.
I have tried Go instead of Python also for basic scripting tasks. Conclusion there was that Python is much simpler with all high-level libraries. I recommend Go only if performance is really a major hurdle.
Cloud Run was easy and cheap choice to host small app with infrequent visits.
Extending the frontend part would not require any changes to the Go web server. You can add any HTML and Javascript files, and the server keeps working.
Build an API with the Go server would require some more learning.
Write a new comment
The name will be visible. Email will not be published. More about privacy.