Skip to content

Instantly share code, notes, and snippets.

@sdtsui
Last active September 13, 2016 22:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sdtsui/8408f5244a463aa4a3349fd4521d842c to your computer and use it in GitHub Desktop.
Save sdtsui/8408f5244a463aa4a3349fd4521d842c to your computer and use it in GitHub Desktop.
first-golang-simpleServer.go
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
)
type UserDetail struct {
Username string
Password string
Email string
}
type User struct {
Id int `json:"id"`
User UserDetail `json:"user"`
}
var firstUserDetail = UserDetail{
Username: "Daniel",
Password: "12345",
Email: "daniel@blacklight.io",
}
var secondUserDetail = UserDetail{
Username: "Daniel2",
Password: "67890",
Email: "dan@blacklight.io",
}
var Users []User
var usersCount = 0
func addUser(count int, detail UserDetail) {
var newUser = User{count, detail}
Users = append(Users, newUser)
usersCount++
}
func init() {
fmt.Println("Initializing server...")
addUser(usersCount, firstUserDetail)
addUser(usersCount, secondUserDetail)
fmt.Println("Initial Users :", Users)
}
func handler(w http.ResponseWriter, request *http.Request) {
u, err := url.Parse(request.RequestURI)
if err != nil {
panic(err)
}
if request.Method == "GET" {
var id = strings.Split(u.Path, "/")
if len(id) < 3 { //No Id
js, err := json.Marshal(Users)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(js)
return
} else if len(id) == 3 {
requestedId, convError := strconv.Atoi(id[2])
if convError != nil {
http.Error(w, convError.Error(), http.StatusInternalServerError)
return
}
for i := 0; i < len(Users); i++ {
if Users[i].Id == requestedId {
js, err := json.Marshal(Users[i])
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(js)
return
}
}
fmt.Println("ID ", requestedId, "Not Found")
w.WriteHeader(http.StatusNotFound)
return
}
return
}
if request.Method == "POST" {
decoder := json.NewDecoder(request.Body)
var u UserDetail
err = decoder.Decode(&u)
if err != nil {
panic(err)
}
addUser(usersCount, u)
w.WriteHeader(http.StatusCreated)
return
}
if request.Method == "PATCH" {
var id = strings.Split(u.Path, "/")
if len(id) < 3 { //No Id
fmt.Println("Update without ID not implemented.")
w.WriteHeader(http.StatusNotImplemented)
return
} else if len(id) == 3 {
requestedId, convError := strconv.Atoi(id[2])
if convError != nil {
http.Error(w, convError.Error(), http.StatusInternalServerError)
return
}
for i := 0; i < len(Users); i++ {
if Users[i].Id == requestedId {
decoder := json.NewDecoder(request.Body)
var u UserDetail
err = decoder.Decode(&u)
if err != nil {
panic(err)
}
newUser := User{requestedId, u}
// update array
leftSide := append(Users[:i], newUser)
Users = append(leftSide, Users[i+1:]...)
fmt.Println("Successful Update, ID:", requestedId)
// send the deleted element
w.WriteHeader(http.StatusAccepted)
return
}
}
//no match
fmt.Println("Update Failed: ID", requestedId, "Not Found")
w.WriteHeader(http.StatusNotFound)
return
}
return
}
if request.Method == "DELETE" {
var id = strings.Split(u.Path, "/")
if len(id) < 3 { //No Id
fmt.Println("Delete without ID not implemented.")
w.WriteHeader(http.StatusNotImplemented)
return
} else if len(id) == 3 {
requestedId, convError := strconv.Atoi(id[2])
if convError != nil {
http.Error(w, convError.Error(), http.StatusInternalServerError)
return
}
for i := 0; i < len(Users); i++ {
if Users[i].Id == requestedId {
js, err := json.Marshal(Users[i])
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
Users = append(Users[:i], Users[i+1:]...)
fmt.Println("Successful Delete, ID:", requestedId)
w.WriteHeader(http.StatusAccepted)
w.Write(js)
return
}
}
fmt.Println("Delete Failed: ID ", requestedId, "Not Found")
w.WriteHeader(http.StatusNotFound)
return
}
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
fmt.Println("Listening...")
fmt.Println("Users...", Users)
http.ListenAndServe(":8000", mux)
}
@sdtsui
Copy link
Author

sdtsui commented Sep 11, 2016

I think I could use advice on the following: (resources/examples appreciated)

  • 12-32 removing globals
  • idiomatic ways to:
    • (34) move manipulation of my Users slice into functions, for update/delete
    • (111) check if a url param exists
    • add statuscodes
    • encode/decode JSON
    • do error checking
  • Using an interface for the following:
    • adding add/update/delete methods for Users
    • when UPDATE receives incomplete details for a user, the server will fail. I'd like to only updating specific fields
    • 2-3 other things?
  • any packages/patterns I should be using
  • anything else you can think of!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment