A closer look at the chat's mumblings The Go Playground was boring so I decided to make a small application that throws me into the language. It basically queries the chatroom every second for new messages and displays them in the output pane (minus the bots their messages).

It's all new to me so any insight is welcome. One thing I've been particularly unsure about are my return statements and whether I'm using them correctly. Likewise, there are a bazillion different ways to declare a variable; have I done it correctly so far?

package main

import (
    "encoding/json"
    "fmt"
    sanitize "github.com/kennygrant/sanitize"
    "html"
    "io/ioutil"
    "net/http"
    "net/url"
    "strconv"
    "time"
)

type ChatEvent struct {
    Event_type    int8
    Time_stamp    int64
    Content       string
    User_id       int64
    User_name     string
    Message_id    int64
    Parent_id     int64
    Show_parent   bool
    Message_Edits int8
    Message_Stars int8
}

type ChatEvents struct {
    Events []ChatEvent
    Time   int64
    Sync   int64
    Ms     int8
}

const (
    Mode         = "Messages"
    ChatUrl      = "http://chat.stackexchange.com/chats/8595/events"
    FKey         = "68f5a3ce293c47399c96ffcd85e0d280" // Go to the chat, F12, reload, look at the /events call and steal its fkey property
    MessageCount = 100                                // Never use this value directly: SE only uses it as a hint and might return a bit more when it feels like it
    Since        = 0
)

var (
    lastMessage int64
)

func main() {
    ticker := time.NewTicker(1 * time.Second)
    quit := make(chan struct{})

    for {
        select {
        case &lt;-ticker.C:
            body := sendRequest()
            parsedJson := parseJson(body)
            newestMessages := getNewestMessages(parsedJson.Events)

            for i := 0; i &lt; len(newestMessages); i++ {
                var currentMessage = newestMessages[i]
                if currentMessage.User_id == -263 || currentMessage.User_id == 125580 {
                    // Ignore Captain Obvious &amp; Duga
                    continue
                }

                fmt.Printf("[%v] %s: %s\n",
                    time.Unix(currentMessage.Time_stamp, 0).Format("15:04:05"),
                    currentMessage.User_name,
                    currentMessage.Content)
            }
        case &lt;-quit:
            ticker.Stop()
            return
        }
    }
}

func sendRequest() (content []byte) {
    response, err := http.PostForm(ChatUrl, url.Values{
        "mode":     {Mode},
        "msgCount": {strconv.Itoa(MessageCount)},
        "fkey":     {FKey},
        "since":    {strconv.Itoa(Since)}})

    if err != nil {
        fmt.Println("Error retrieving response")
        fmt.Println(err.Error())
        return nil
    }

    defer response.Body.Close()
    content, err = ioutil.ReadAll(response.Body)
    if err != nil {
        fmt.Println("Error reading response")
        fmt.Println(err.Error())
        return nil
    }

    return
}

func parseJson(body []byte) (parsedJson ChatEvents) {
    err := json.Unmarshal(body, &amp;parsedJson)
    if err != nil {
        fmt.Println("Error parsing json")
        fmt.Println(err.Error())
        return
    }

    return
}

func getNewestMessages(events []ChatEvent) (output []ChatEvent) {
    output = make([]ChatEvent, 0)

    for index := 0; index &lt; len(events); index++ {
        if events[index].Time_stamp &gt; lastMessage {
            events[index].Content = html.UnescapeString(sanitize.HTML(events[index].Content))
            output = append(output, events[index])
            lastMessage = events[index].Time_stamp
        }
    }

    return
}
Disclaimer: I don't know Go.

Error handling

The sendRequest method may fail,
returning nil,
but the caller in main continues happily as if nothing happened.
In fact, looking at the context of the call in main,
my first impression was that sendRequest magically always succeeds,
which is not the case, and so a bit misleading.

Likewise, parseJson may also fail,
parsing nothing,
but from where you call it,
this is not obvious, which is again a bit misleading.

Naming

It seems [the common convention][1] is to use camelCase or PascalCase for names,
no underscores.
So I suggest to rename the fields of the ChatEvent struct.
I'd go as far as to say use PascalCase for types and camelCase for variables, but this is not so clear in the docs.

The variable parsedJson says nothing about what kind of object it is.
So I'd rename it to chatEvents.

Exceptional users

The list of such users would be better in a global set:


if currentMessage.User_id == -263 || currentMessage.User_id == 125580 {
    // Ignore Captain Obvious &amp; Duga
    continue
}



Too wide lines

The line-end comments in the constant definitions make me scroll to the far right to read them.
Even worse,
while reading the code further down,
when I see lines that seem to end near the right end of the text,
the presence of the horizontal scrollbar makes me wonder if there's something more if I scroll right.
And usually there's nothing, as expected, but this is really annoying.
Please avoid line-end comments if they make the line wider than the longest real line of code.
Or better yet, avoid line-end comments if they will make the line exceed 70 characters.