1
\$\begingroup\$

I have created a Golang WebApp that shows the time. I am new to the Golang programming language so thought this little app would allow me to use golang as a webserver, learn about goroutines and websockets which I am also new to.

I would like to know if my code follows best practices especially regarding goroutines/threading and the use of websockets.

Index.html

<!doctype html>
<html class="no-js" lang="">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>

<body>
  <!--[if lt IE 8]>
    <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
  <![endif]-->

  <h1>Golang Clock WebApp</h1>

  <h3>
    <span id="name">Header Text</span>
    <button id="get-time-manually">Update Time</button>
  </h3>
  <hr/>

  <div id="container"></div>

  <script type="text/javascript">
    $( document ).ready(function() {
      getTime();

      $( "#get-time-manually" ).click(function() {
        getTime();
      });

      var ws;
      if (window.WebSocket === undefined) {
          $("#container").append("Your browser does not support WebSockets");
          return;
      } else {
          ws = initWS();
      }
    });

    function getTime() {
      $.get( "/time", function( data ) {
        $( "#name" ).html( JSON.parse(data) );
      });
    };

    function initWS() {
      var socket = new WebSocket("ws://localhost:8080/ws"),
        container = $("#container")
        socket.onmessage = function (e) {
            $( "#name" ).html( JSON.parse(e.data) );
        };

      return socket;
    };
  </script>
</body>

</html>

main.go

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "time"

    "github.com/gorilla/mux"
    "github.com/gorilla/websocket"
)

func newRouter() *mux.Router {
    router := mux.NewRouter()

    router.HandleFunc("/time", getTimeHandler).Methods("GET")
    router.HandleFunc("/ws", getWebSocketHandler)

    // /assets/ Page
    staticFileDirectory := http.Dir("./assets/")
    staticFileHandler := http.StripPrefix("/assets/", http.FileServer(staticFileDirectory))
    router.PathPrefix("/assets/").Handler(staticFileHandler).Methods("GET")

    return router
}

func main() {
    router := newRouter()

    http.ListenAndServe(":8080", router)
}

func getTimeHandler(w http.ResponseWriter, r *http.Request) {

    timeBytes, err := json.Marshal(getTimeNow())

    // If there is an error, print it to the console, and return a server
    // error response to the user
    if err != nil {
        fmt.Println(fmt.Errorf("Error: %v", err))
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    // If all goes well, write the JSON to the response
    w.Write(timeBytes)
}

func getWebSocketHandler(w http.ResponseWriter, r *http.Request) {

    if r.Header.Get("Origin") != "http://"+r.Host {
        //"ws://" + location.host + "/ws"
        http.Error(w, "Origin not allowed", 403)
        return
    }

    conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
    if err != nil {
        http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
    }

    go timeRoutine(conn)

}

func timeRoutine(conn *websocket.Conn) {

    t := time.NewTicker(time.Second * 3)
    for {

        timeString := getTimeNow()

        if err := conn.WriteJSON(timeString); err != nil {
            fmt.Println(err)
        }

        <-t.C
    }
}

func getTimeNow() string {
    timeNow := time.Now()
    formattedTime := timeNow.Format("Mon Jan 02 15:04:05 MST 2006")

    return formattedTime
}

The full repo can be found here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.