Thread safe counter pattern


(B Dev) #1

Hi,
So, I would like to understand if the program pattern below is idiomatic or not? Moreover any comments in regard to code styles are welcome

I am creating a small service to fetch and update counters. I would like to make them thread safe and do not want to create any global variable as such.

Here is the small program

package main

import (
	"fmt"
	"net/http"
	"strconv"

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

type counter struct {
	feedService FeedService
}

type FeedService interface {
	UpdateCounter(input int)
	GetCounter() int
	CounterService()
}

type Feed struct {
	Update chan int
	Get    chan bool
	Fetch  chan int
}

func (f Feed) UpdateCounter(input int) {
	f.Update <- input
	return
}

func (f Feed) GetCounter() int {
	f.Get <- true
	out := <-f.Fetch
	return out
}

func (f Feed) CounterService() {

	counter := 0

	for {
		select {
		case msg := <-f.Update:
			counter += msg
		case <-f.Get:
			f.Fetch <- counter
		}
	}
}

func (c *counter) Router() *mux.Router {
	r := mux.NewRouter()
	r.HandleFunc("/get", c.Fetch)
	r.HandleFunc("/update", c.Update)
	return r
}

func (c *counter) Fetch(w http.ResponseWriter, r *http.Request) {

	out := c.feedService.GetCounter()
	outstr := strconv.Itoa(out)
	fmt.Fprintf(w, outstr)
}

func (c *counter) Update(w http.ResponseWriter, r *http.Request) {
	c.feedService.UpdateCounter(1)
	fmt.Fprintf(w, "OK")
}
func main() {

	f := Feed{
		Update: make(chan int),
		Get:    make(chan bool),
		Fetch:  make(chan int),
	}
	c := counter{&f}
	go c.feedService.CounterService()
	log.Fatal(http.ListenAndServe(":8013", c.Router()))

}

Thanks
Bdev