Skip to content

Commit fdf989b

Browse files
committed
Merge pull request reactjs#28 from freeformz/go
Add a go sample
2 parents bb3bae4 + c0d91fa commit fdf989b

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,9 @@ ruby server.rb
3030
php server.php
3131
```
3232

33+
### Go
34+
```sh
35+
go run server.go
36+
```
37+
3338
And visit <http://localhost:3000/>. Try opening multiple tabs!

server.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"log"
8+
"net/http"
9+
"os"
10+
"sync"
11+
)
12+
13+
type comment struct {
14+
Author string `json:"author"`
15+
Text string `json:"text"`
16+
}
17+
18+
const dataFile = "./_comments.json"
19+
20+
var commentMutex = new(sync.Mutex)
21+
22+
// Handle comments
23+
func handleComments(w http.ResponseWriter, r *http.Request) {
24+
// Since multiple requests could come in at once, ensure we have a lock
25+
// around all file operations
26+
commentMutex.Lock()
27+
defer commentMutex.Unlock()
28+
29+
// Stat the file, so we can find it's current permissions
30+
fi, err := os.Stat(dataFile)
31+
if err != nil {
32+
http.Error(w, fmt.Sprintf("Unable to stat data file (%s): %s", dataFile, err), http.StatusInternalServerError)
33+
return
34+
}
35+
36+
// Open the file Read/Write
37+
cFile, err := os.OpenFile(dataFile, os.O_RDWR, fi.Mode())
38+
if err != nil {
39+
http.Error(w, fmt.Sprintf("Unable to open data file (%s): %s", dataFile, err), http.StatusInternalServerError)
40+
return
41+
}
42+
defer cFile.Close() //Ensure the file is closed when we are done.
43+
44+
switch r.Method {
45+
case "POST":
46+
// Decode the JSON data
47+
comments := make([]comment, 0)
48+
commentsDecoder := json.NewDecoder(cFile)
49+
if err := commentsDecoder.Decode(&comments); err != nil {
50+
http.Error(w, fmt.Sprintf("Unable to read comments from data file (%s): %s", dataFile, err), http.StatusInternalServerError)
51+
return
52+
}
53+
54+
// Add a new comment to the in memory slice of comments
55+
comments = append(comments, comment{Author: r.FormValue("author"), Text: r.FormValue("text")})
56+
57+
// Truncate the file and Seek to the beginning of it
58+
if err := cFile.Truncate(0); err != nil {
59+
http.Error(w, fmt.Sprintf("Unable to truncate data file (%s): %s", dataFile, err), http.StatusInternalServerError)
60+
return
61+
}
62+
if r, err := cFile.Seek(0, 0); r != 0 && err != nil {
63+
http.Error(w, fmt.Sprintf("Unable to seek to beginning of data file (%s): %s", dataFile, err), http.StatusInternalServerError)
64+
return
65+
}
66+
67+
// Write out the json response
68+
commentsEncoder := json.NewEncoder(cFile)
69+
commentsEncoder.Encode(comments)
70+
71+
case "GET":
72+
// stream the contents of the file to the response
73+
io.Copy(w, cFile)
74+
75+
default:
76+
// Don't know the method, so error
77+
http.Error(w, fmt.Sprintf("Unsupported method: %s", r.Method), http.StatusMethodNotAllowed)
78+
}
79+
}
80+
81+
func main() {
82+
http.HandleFunc("/comments.json", handleComments)
83+
http.Handle("/", http.FileServer(http.Dir("./public")))
84+
log.Fatal(http.ListenAndServe(":3000", nil))
85+
}

0 commit comments

Comments
 (0)