An open API service indexing awesome lists of open source software.

https://github.com/debck/learning-go

List of concepts and code snippets that would help in learning Golang and apply in Web Development 🎉
https://github.com/debck/learning-go

concepts database forms golang learning-golang middleware middlware parsing-xml-data routes snippets study unit-testing webdevelopment

Last synced: about 1 month ago
JSON representation

List of concepts and code snippets that would help in learning Golang and apply in Web Development 🎉

Awesome Lists containing this project

README

        




A simple list of concepts and code snippets that would help in learning Golang and apply in Web Development :tada:. I tried to jot down when I was learning. It might be helpful for beginners who want to learn Go for web development.



[![Open Source](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://opensource.org/)
[![GitHub license](https://img.shields.io/github/license/debck/Learning-Go?style=flat-square)](https://github.com/debck/Learning-Go/blob/master/LICENSE) ![Maintenance](https://img.shields.io/maintenance/yes/2020?style=flat-square) ![GitHub last commit](https://img.shields.io/github/last-commit/debck/Learning-Go?style=flat-square)
[![HitCount](http://hits.dwyl.com/debck/Learning-Go.svg)](http://hits.dwyl.com/debck/Learning-Go)

> ✌️ Hope you find something useful. If you like it please give it a 🌟.

## Contents
* [Installation](#Installation)
* [Concepts to learn before diving into Web](#Initial-Concepts-to-Study-before-diving-deep)
* [Basic Hello World](#Basic-Hello-World)
* [Adding static assets](#Adding-static-asset)
* [Creating Routes](#Adding-Routes)
* [Adding Forms](#Adding-Forms)
* [Adding MiddleWare](#Adding-MiddleWare)
* [Sessions Management](#Sessions-Management)
* [Adding Database](#Adding-Database)
* [MongoDB](#MongoDB)
* [Writing Unit Test](#Writing-Unit-Test)
* [Parsing XML Data](#Parsing-XML-Data)
* [File Uploading](#File-Uploading)

## Installation

> Follow the [official doc](https://golang.org/doc/install) and setup Go depending on your OS (ie. Windows , Linux, OS X)

## Initial Concepts to Study before diving deep

* Basic Understanding of
* Variables
* Constants
* Packages and import/export
* Functions
* Pointers
* Mutability
* Types
* Type Conversion
* Type assertion**
* Structs
* Composition
* Collection Types
* Arrays
* Slicing
* Range & Maps
* Control Flow
* If, For, Switch statement
* Methods
* Interfaces
* Concurrency
* Goroutines
* Channels

## Basic Hello World

```go
package main

import (
"fmt"
"net/http"
)

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World !")
})

http.ListenAndServe(":8000", nil)
}
```
[Go back to top ↑](#Contents)

## Adding static asset

When we want to serve static files like CSS, JavaScript or images to Web.

```go
func main() {
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
})

fs := http.FileServer(http.Dir("./static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))

http.ListenAndServe(":8000", nil)
}
```
[Go back to top ↑](#Contents)

## Adding Routes

```go
package main

import (
"fmt"
"encoding/json"
"net/http"
"github.com/gorilla/mux"
)

type Tasks struct {
ID string `json:"id,omitempty"`
TASKNAME string `json:"task,omitempty"`
}

var task []Tasks

func getAllTask(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(task)
}

func getTask(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
for _,item := range task {
if item.ID == params["id"] {
json.NewEncoder(w).Encode(item)
return
}
}
json.NewEncoder(w).Encode(&Tasks{})
}

func main() {
router := mux.NewRouter()
router.HandleFunc("/task", getAllTask).Methods("GET")
router.HandleFunc("/task/{id}", getTask).Methods("GET")

http.ListenAndServe(":8000", router)
}

```

[Go back to top ↑](#Contents)

## Adding Forms

Considering the form has 2 fields `Email` and `Message`.

```go

package main

import (
"log"
"fmt"
"net/http"
)

type Details struct {
Email string
Message string
}

func messageHandle(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
fmt.Fprintf(w, "ParseForm() err: %v", err)
return
}

data := Details{
Email: r.FormValue("email"),
Message: r.FormValue("message"),
}

// do something with the data
}

func main() {
http.HandleFunc("/", messageHandle)

if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}

```

[Go back to top ↑](#Contents)

## Adding MiddleWare

Here, the `Middleware` function allows adding more than one layer of middleware and handle them appropriately.
`SomeMiddleware` is the middleware function which gets called before the route handler function `getAllTask`

```go

package main

import (
"encoding/json"
"log"
"net/http"
"github.com/gorilla/mux"
)

func getAllTask(w http.ResponseWriter, r *http.Request) {
// ... do something inside this route
}

// Function allows adding more than one layer of middleware and handle them appropriately

func Middleware(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
for _, mw := range middleware {
h = mw(h)
}
return h
}

// Middlware function

func SomeMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

// ... do middleware things

next.ServeHTTP(w, r)
})
}

func main() {

router := mux.NewRouter()
router.Handle("/task", Middleware(
http.HandlerFunc(getAllTask),
SomeMiddleware,
))
log.Fatal(http.ListenAndServe(":8000", router))
}

```

[Go back to top ↑](#Contents)

## Sessions Management

```go

import (
"os"
"log"
"net/http"
"github.com/gorilla/sessions"
)

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))

func Handlerfunction(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

// Set some session values.
session.Values["hello"] = "world"
// Save it
session.Save(r, w)
}

func main() {
http.HandleFunc("/", Handlerfunction)

if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}

```

[Go back to top ↑](#Contents)

## Adding Database

### MongoDB

Here in this example we have connected MongoDB with our application and saved sample data into the collection

```go

package main

import (
"context"
"fmt"
"os"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

type Data struct {
ID int `json:"Field Int"`
Task string `json:"Field Str"`
}

func main() {

clientOptions := options.Client().ApplyURI("")

// Connect to the MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)

if err != nil {
fmt.Println("mongo.Connect() ERROR:", err)
os.Exit(1)
}

// To manage multiple API requests
ctx, _ := context.WithTimeout(context.Background(), 15*time.Second)

// Access a MongoDB collection through a database
col := client.Database("DATABASE_NAME").Collection("COLLECTION_NAME")

// Declare a MongoDB struct instance for the document's fields and data
newData := Data{
ID: 12,
Task: "Learn Go",
}

result, err := col.InsertOne(ctx, newData)
if err != nil {
fmt.Println("ERROR:", err)
os.Exit(1)

} else {
fmt.Println("Result:", result)
}
}

```

[Go back to top ↑](#Contents)

## Writing Unit Test

Consider the [Adding Routes](#Adding-Routes) section for testing. The below test case is for the `/task` route which returns an array of tasks created by users.

```go

package main

import (
"net/http"
"testing"
"net/http/httptest"
"strings"
)

func TestGetAllTask(t *testing.T) {
req, err := http.NewRequest("GET", "http://localhost:8000/task", nil)
if err != nil {
t.Fatal(err)
}
res := httptest.NewRecorder()
handler := http.HandlerFunc(getAllTask)
handler.ServeHTTP(res, req)

if status := res.Code; status != http.StatusOK {
t.Errorf("Wrong Status Code: got %v want %v",
status, http.StatusOK)
}

// Check the response body is what we expect.
expected := `[{"id":"1","task":"Hello"},{"id":"2","task":"World"},{"id":"3","task":"yeah"}]`

if strings.TrimRight(res.Body.String(),"\n") != expected {
t.Errorf("ERROR: got %v want %v",
res.Body.String(), expected)
}
}

```
Remember Test file should be name of original file + test like: `base.go` - `base_test.go`.(good practice)

After running the above test case by `go test -v` command, the following output will appear

```bash
F:\Go\src\Rest_API>go test -v
=== RUN TestGetAllTask
--- PASS: TestGetAllTask (0.00s)
PASS
ok Rest_API 0.454s
```

[Go back to top ↑](#Contents)

## Parsing XML Data

For example we have taken [this](https://github.com/debck/Learning-Go/blob/master/assets/foods.xml) XML file for parsing.

```go
package main

import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
)

// struct which contains the array of all Foods in the file.
type Foods struct {
Foods []Food `xml:"food"`
}

// struct which contains the details of one food.
type Food struct {
Name string `xml:"name"`
Price string `xml:"price"`
Calories string `xml:"calories"`
}

func main() {
// Open xml file
xmlFile, err := os.Open("foods.xml")

if err != nil {
fmt.Println(err)
}

// defer the closing of our xmlfile so that we can parse later
defer xmlFile.Close()

// read the xml file as a byte array.
byteValue, _ := ioutil.ReadAll(xmlFile)

var f Foods

xml.Unmarshal(byteValue, &f)

// Do something with the info.....

// Here, we print out the Foods as just an example

fmt.Println("______MENU______")
for i := 0; i < len(f.Foods); i++ {
fmt.Println(f.Foods[i].Name + " " + f.Foods[i].Price + " " + f.Foods[i].Calories)
}

}

```
After running the above program, the following output will appear

```bash
F:\Go\src\Code>go run parsexml.go
______MENU______
Belgian Waffles $5.95 650
French Toast $4.50 600
```

[Go back to top ↑](#Contents)

## File Uploading

> Todo

## Contribute

Contributions are always welcome! Please open an [issue](https://github.com/debck/Learning-Go/issues/new) if you think something should be added to the list.

## Licence

MIT © [Debasish Sahoo](https://github.com/debck/Learning-Go/blob/master/LICENSE)