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 🎉
- Host: GitHub
- URL: https://github.com/debck/learning-go
- Owner: debck
- License: mit
- Created: 2020-04-28T13:17:26.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2020-05-31T06:36:33.000Z (almost 5 years ago)
- Last Synced: 2025-03-18T04:52:02.543Z (about 1 month ago)
- Topics: concepts, database, forms, golang, learning-golang, middleware, middlware, parsing-xml-data, routes, snippets, study, unit-testing, webdevelopment
- Homepage:
- Size: 68.4 KB
- Stars: 48
- Watchers: 1
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: Readme.md
- License: LICENSE
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.
[](https://opensource.org/)
[](https://github.com/debck/Learning-Go/blob/master/LICENSE)  
[](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 mainimport (
"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 mainimport (
"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 thingsnext.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 mainimport (
"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)