Даниел обнови решението на 21.01.2016 00:02 (преди над 2 години)
+package main
+
+import (
+        "encoding/json"
+        "fmt"
+        "io/ioutil"
+        "net/http"
+        "strconv"
+)
+
+type empty struct{}
+type pair [2]int64
+
+type GameOfLifeHandler struct {
+        alive map[pair]empty
+        gen   int64
+        *http.ServeMux
+}
+
+type cellStatusS struct {
+        Alive bool `json:"alive"`
+}
+
+type generationS struct {
+        Generation int64  `json:"generation"`
+        Living     []pair `json:"living"`
+}
+
+type cellsS struct {
+        Cells []struct {
+                X int64 `json:"x"`
+                Y int64 `json:"y"`
+        }
+}
+
+func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
+        golh := &GameOfLifeHandler{map[pair]empty{}, 0, http.NewServeMux()}
+
+        for _, v := range cells {
+                golh.alive[v] = empty{}
+        }
+
+        golh.HandleFunc("/cell/status/", func(rw http.ResponseWriter, r *http.Request) {
+                defer r.Body.Close()
+                if r.Method == "GET" {
+                        q := r.URL.Query()
+                        x, errx := strconv.ParseInt(q["x"][0], 10, 64)
+                        y, erry := strconv.ParseInt(q["y"][0], 10, 64)
+                        if errx != nil || erry != nil {
+                                rw.WriteHeader(http.StatusBadRequest)
+                                fmt.Fprintf(rw, "'x' and 'y' should be int64s")
+                                return
+                        }
+                        rw.WriteHeader(http.StatusOK)
+                        res, _ := json.Marshal(golh.getCellStatus(x, y))
+                        fmt.Fprintf(rw, "%s", res)
+                } else {
+                        rw.WriteHeader(http.StatusMethodNotAllowed)
+                }
+        })
+        golh.HandleFunc("/generation/", func(rw http.ResponseWriter, r *http.Request) {
+                defer r.Body.Close()
+                if r.Method == "GET" {
+                        rw.WriteHeader(http.StatusOK)
+                        res, _ := json.Marshal(golh.getGeneration())
+                        fmt.Fprintf(rw, "%s", res)
+                } else {
+                        rw.WriteHeader(http.StatusMethodNotAllowed)
+                }
+        })
+        golh.HandleFunc("/cells/", func(rw http.ResponseWriter, r *http.Request) {
+                defer r.Body.Close()
+                if r.Method == "POST" {
+                        var cells cellsS
+                        contents, err := ioutil.ReadAll(r.Body)
+                        if err != nil {
+                                rw.WriteHeader(http.StatusBadRequest)
+                                fmt.Fprintf(rw, "I failed with reading the request's body")
+                                return
+                        }
+                        err = json.Unmarshal(contents, &cells)
+                        if err != nil {
+                                rw.WriteHeader(http.StatusBadRequest)
+                                fmt.Fprintf(rw, "Malformed json was passed")
+                                return
+                        }
+                        var cellsSlice []pair
+                        for _, v := range cells.Cells {
+                                cellsSlice = append(cellsSlice, pair{v.X, v.Y})
+                        }
+                        golh.postCells(cellsSlice)
+                        rw.WriteHeader(http.StatusNoContent)
+                } else {
+                        rw.WriteHeader(http.StatusMethodNotAllowed)
+                }
+        })
+        golh.HandleFunc("/generation/evolve/", func(rw http.ResponseWriter, r *http.Request) {
+                defer r.Body.Close()
+                if r.Method == "POST" {
+                        golh.postGenerationEvolve()
+                        rw.WriteHeader(http.StatusNoContent)
+                } else {
+                        rw.WriteHeader(http.StatusMethodNotAllowed)
+                }
+        })
+        golh.HandleFunc("/reset/", func(rw http.ResponseWriter, r *http.Request) {
+                defer r.Body.Close()
+                if r.Method == "POST" {
+                        golh.postReset()
+                        rw.WriteHeader(http.StatusNoContent)
+                } else {
+                        rw.WriteHeader(http.StatusMethodNotAllowed)
+                }
+        })
+
+        return golh
+}
+
+func (g *GameOfLifeHandler) getCellStatus(x int64, y int64) cellStatusS {
+        _, ok := g.alive[pair{x, y}]
+        return cellStatusS{ok}
+}
+
+func (g *GameOfLifeHandler) getGeneration() generationS {
+        var cells []pair
+        for k, _ := range g.alive {
+                cells = append(cells, k)
+        }
+        return generationS{g.gen, cells}
+}
+
+func (g *GameOfLifeHandler) postCells(cells []pair) {
+        for _, i := range cells {
+                if _, ok := g.alive[i]; !ok {
+                        g.alive[i] = empty{}
+                }
+        }
+}
+
+func (g *GameOfLifeHandler) postGenerationEvolve() {
+        g.gen++
+        cells := g.significantCells()
+
+        for k, _ := range cells {
+                n := g.neighbours(k[0], k[1])
+                if _, ok := g.alive[k]; (ok && n == 2) || n == 3 {
+                        g.alive[k] = empty{}
+                } else {
+                        delete(g.alive, k)
+                }
+        }
+}
+
+var nes = [...]pair{{-1, -1}, {-1, 0}, {-1, 1},
+        {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}
+
+func (g *GameOfLifeHandler) significantCells() map[pair]empty {
+        cells := g.alive
+        for k, _ := range g.alive {
+                for _, v := range nes {
+                        cells[pair{k[0] + v[0], k[1] + v[1]}] = empty{}
+                }
+        }
+        return cells
+}
+
+func (g *GameOfLifeHandler) neighbours(x int64, y int64) int8 {
+        count := int8(0)
+        for _, v := range nes {
+                if _, ok := g.alive[pair{x + v[0], y + v[1]}]; ok {
+                        count++
+                }
+        }
+        return count
+}
+
+func (g *GameOfLifeHandler) postReset() {
+        g.alive = map[pair]empty{}
+        g.gen = 0
+}
Мого хубаво решение. Особено ми харесва type empty struct{}. Мисля, че можеш да го направиш още по - добро ако го пробваш с конкурентни кънекции за различни endpoint-и. Знай, че go HTTP сървърите правят отделна goroutine-а за всяка кънекция. Това, потенциално, е отделна нишка.
Сега прочетох по - внимателно решението ти. Пробвал ли си добавяне на клетки? Пробвал ли си еволюцията? Ако си напишеш по един тест за тези две неща няма да сгрешиш.
