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.


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

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <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>

  <!--[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>

  <h1>Golang Clock WebApp</h1>

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

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

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

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

      var ws;
      if (window.WebSocket === undefined) {
          $("#container").append("Your browser does not support WebSockets");
      } 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;



package main

import (


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))

    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))

    // If all goes well, write the JSON to the response

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)

    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 {


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


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.