2
\$\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\$

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.