Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
August 22, 2021 06:58 am GMT

Create CRUD Apps with http/net Golang without database

This article just have a purpose to show how to create CRUD (Create, Read, Update & Delete) Apps just using http/net.

First step we need to create project directory.

mkdir golang-basic-http # create directory projectcd golang-basic-http # go to projectgo mod init golang-basic-http # initialize go module inside the project

Next, please create file main.go, with touch main.go inside the project directory.

package mainimport "fmt"func main() {   fmt.Println("Hello world")}

Than, execute the main.go.

go run main.goHello world # the result

Next, we need to import http/net and create the http server.

package mainimport (    "log"    "net/http")func main() {    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {        rw.Write([]byte("Hello World"))    })    log.Fatal(http.ListenAndServe(":8000", nil))}

Ok, http.HandleFunc have 2 parameters, to fill with route path and handler, path describe the route, and handler is a function, and the function have 2 parameters http.ResponseWriter to write the output, and http.Request to catch the request from http.

Next, inside handler we need to create response Hello World if user access the path.

// rw is http.ResponseWriterrw.Write([]byte("Hello world"))

And to listens on the TCP network we using http.ListenAndServer.

http.ListenAndServer(":8000", nil)

http.ListenAndServer have 2 parameters, first parameter fill with the port address, and next with route config, because we don't use router configuration, for this time, second parameter in http.ListenAndServer we can fill with nil.

If you access the http with port 8000 using curl in the terminal.

curl -i http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 04:58:38 GMTContent-Length: 11Content-Type: text/plain; charset=utf-8Hello world%

Yes, congratulations.

Next, we need create methods GET, POST, DELETE, and PUT inside the handler.

To get methods, we need access r in http.Request.

 switch r.Method {    case "GET":      rw.Write([]byte("GET/ Hello World"))    case "POST":      rw.Write([]byte("POST/ Hello World")) }

Try to access GET

curl -i http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 05:26:01 GMTContent-Length: 16Content-Type: text/plain; charset=utf-8GET/ Hello World%

Next, try to access POST

curl -i -X POST http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 05:25:44 GMTContent-Length: 17Content-Type: text/plain; charset=utf-8POST/ Hello World%

Ok, next we need to define data, example Todo with have Task and ID.

type Todo struct {    ID   int    Task string}func main() {...

...and, define collection of Todo, in todos variable.

type Todo struct {    ID   int    Task string}var todos []Todofunc main() {...

...next we need to access todos, inside handler.

switch r.Method {case "GET":  json.NewEncoder(rw).Encode(todos)...

json.NewEncoder(rw).Encode(todos) convert todos and encode to json format as the result.

Save, and next run go run main.go

HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 05:54:23 GMTContent-Length: 5Content-Type: text/plain; charset=utf-8null

Oops, the result is null cause todos is empty, we need to create post to fill todos with new value.

case "POST":   // create variable to save todo   var todo Todo   // decode `r.Body` `r *http.Request` to get data from request   // decode the result to todo   json.NewDecoder(r.Body).Decode(&todo)   // append new todo in todos   todos = append(todos, todo)   // finally, encode again create the resutl with json format   json.NewEncoder(rw).Encode(todo)}

...next, save and try again, we need to access POST to save new value.

curl -i -X POST -d '{"ID": 1, "Task": "Coding..."}' http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:01:37 GMTContent-Length: 28Content-Type: text/plain; charset=utf-8{"ID":1,"Task":"Coding..."}

...next, access GET.

curl -i http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:01:59 GMTContent-Length: 30Content-Type: text/plain; charset=utf-8[{"ID":1,"Task":"Coding..."}]

Next, we need add method DELETE to remove todo base on the ID in todo.

case "DELETE":  // http/net not support path variable like this `/:id`  // and to handle it, we using `r.URL.Query` to get the query url  // http://localhost:8000?id=1  query := r.URL.Query()  // id result have a type string  // we need `strconv.Atoi` to convert string into int  id, _ := strconv.Atoi(query.Get("id"))  // next we need to loop todos, and match the id with todo.ID  for index, todo := range todos {     if todo.ID == id {        // splice and replace the todo        todos = append(todos[:index], todos[index+1:]...)        rw.Write([]byte("Success to deleted todo"))     }  }

...save, and run again

curl -i http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:25:21 GMTContent-Length: 30Content-Type: text/plain; charset=utf-8[{"ID":1,"Task":"Coding..."}]
curl -i -X DELETE http://localhost:8000\?id\=1HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:26:30 GMTContent-Length: 23Content-Type: text/plain; charset=utf-8Success to deleted todo%
curl -i http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:27:00 GMTContent-Length: 3Content-Type: text/plain; charset=utf-8[]
 case "PUT":    query := r.URL.Query()    id, _ := strconv.Atoi(query.Get("id"))    for index, todo := range todos {       json.NewDecoder(r.Body).Decode(&todo)       if todo.ID == id {          todos[index].ID = todo.ID          todos[index].Task = todo.Task          rw.Write([]byte("Success to update todo"))       }    }}

...yup, save, and run again

curl -i -X POST -d '{"ID": 1, "Task": "Coding..."}' http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:33:35 GMTContent-Length: 28Content-Type: text/plain; charset=utf-8{"ID":1,"Task":"Coding..."}---curl -i http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:34:10 GMTContent-Length: 30Content-Type: text/plain; charset=utf-8[{"ID":1,"Task":"Coding..."}]

...update data

curl -i -X PUT -d '{"ID": 1, "Task": "Bobo siang"}' http://localhost:8000\?id\=1HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:35:32 GMTContent-Length: 22Content-Type: text/plain; charset=utf-8Success to update todo%---curl -i http://localhost:8000HTTP/1.1 200 OKDate: Sun, 22 Aug 2021 06:39:24 GMTContent-Length: 35Content-Type: text/plain; charset=utf-8[{"ID": 1, "Task": "Bobo siang"}]

Yes, congratulations!, and next we need to custom header, and need a little refactor.

package mainimport (    "encoding/json"    "log"    "net/http"    "strconv")type Todo struct {    ID   int    Task string}var todos []Todofunc main() {    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {        rw.Header().Add("Content-Type", "application/json")        rw.Header().Add("Access-Control-Allow-Origin", "*")        query := r.URL.Query()        id, _ := strconv.Atoi(query.Get("id"))        switch r.Method {        case "GET":            rw.WriteHeader(http.StatusOK)            json.NewEncoder(rw).Encode(todos)        case "POST":            var todo Todo            json.NewDecoder(r.Body).Decode(&todo)            todos = append(todos, todo)            rw.WriteHeader(http.StatusOK)            json.NewEncoder(rw).Encode(todo)        case "DELETE":            for index, todo := range todos {                if todo.ID == id {                    todos = append(todos[:index], todos[index+1:]...)                    rw.WriteHeader(http.StatusOK)                    rw.Write([]byte(`{"message": "Success to delete todo"}`))                }            }        case "PUT":            for index, todo := range todos {                if todo.ID == id {                    json.NewDecoder(r.Body).Decode(&todo)                    todos[index].ID = todo.ID                    todos[index].Task = todo.Task                    rw.WriteHeader(http.StatusOK)                    rw.Write([]byte(`{"message": "Success to update todo"}`))                }            }        }    })    log.Fatal(http.ListenAndServe(":8000", nil))}
curl http://localhost:8000 -v*   Trying ::1...* TCP_NODELAY set* Connected to localhost (::1) port 8000 (#0)> GET / HTTP/1.1> Host: localhost:8000> User-Agent: curl/7.64.1> Accept: */*>< HTTP/1.1 200 OK< Access-Control-Allow-Origin: *< Content-Type: application/json< Date: Sun, 22 Aug 2021 06:54:01 GMT< Content-Length: 5<null* Connection #0 to host localhost left intact* Closing connection 0

Yes, hopefully you can learn something with this basic article about http server in golang.


Original Link: https://dev.to/adiatma/create-crud-apps-with-http-net-golang-without-database-18ip

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To