Showing posts with label go. Show all posts
Showing posts with label go. Show all posts

GoLang: Quick gist on Difference between Marshal, Unmarshal, Encoder and Decoder

Summary: Marshal, Unmarshal and Encode, Decode

Summary: Marshal, Unmarshal and Encode, Decode

  • Marshal: Convert struct/map interface data into JSON.
  • Unmarshal: Convert JSON data into struct/map

If reading from a file involved, then you read it in []byte format. To read from a file

  • using os.Open open the file.

  • then read all the data using io.ReadAll method.

  • Encoder and Decoder kind of do reading/writing internally. More like a simplified version of Marshal and Unmarshal.

  • Encoder converts the struct/map into JSON and automatically writes into io.Writer

  • Decoder reads from io.Writer and convert the JSON data into struct/map interface.

If there is a byte slice to work with, use Marshal and Unmarshal. If there is an io.Writer or an io.Reader, use Encode and Decode.

Ref: https://blog.devgenius.io/to-unmarshal-or-to-decode-json-processing-in-go-explained-e92fab5b648f

GoLang: How to render a web template using Gin framework and render data from map ?

 I have struggled lot of time, to break this into working modal. So below code, is working example where you can have your data in a slice of URLs and render that data using Go Templates. 

I am giving a skeleton HTML template, not adding any thing extra. 

I believe the code itself is self explanatory, if any questions, please dont hesitate to ask.


main.go

package main

import (
"log"
"net/http"

"github.com/gin-gonic/gin"
)

type URL struct {
Name string
Url string
}

var URLs = []URL{
{Name: "google", Url: "google.com"},
{Name: "yahoo", Url: "yahoo.com"},
{Name: "gmail", Url: "gmail.com"},
}

func main() {

router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.GET("/", bookmarks)
router.GET("/hello", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.tmpl", gin.H{
"title": "Main website",
"Items": URLs,
})
})

log.Fatal(router.Run(":8000"))
}

func bookmarks(c *gin.Context) {
c.HTML(http.StatusOK, "index.tmpl", gin.H{
"title": "Bookmarks",
"URLs": URLs,
})
}

Go Templates will be stored inside templates directory, so create a templates directory where you have your main.go file and have that file as below 

index.tmpl


<html>
<h1>
{{ .title }}
</h1>
<body>
{{ range .URLs}}
{{.Name}}
{{.Url}}
{{end}}
</body>
</html>

Hope it helps.

Thank you.

GoLang: How To work with JSON Data and Nested structs

GoLang: How To work with JSON Data and Nested structs

Hello Everyone,

I spent sometime today to craft this code, so this article slowly walk you through how to build a nested struct, how to load data into it, then converting it into JSON, writing to a file, reading from a file and append new data etc.

I was learning GoLang and found needed something like this. Hope it helps.

package main

import (
	"encoding/json"
	"fmt"
	"os"
)

type Schema struct {
	Users map[string]User
	Posts map[string]Post
}

type User struct {
	Username string `json:"username"`
	Email    string `json:"email"`
}
type Post struct {
	Heading     string `json:"post_heading"`
	Description string `json:"description"`
}

func main() {
	u1 := User{
		Username: "rajag",
		Email:    "rajag@example.com",
	}

	p1 := Post{
		Heading:     "Post 1 heading",
		Description: "Post 1 description",
	}

	fmt.Println(u1)
	fmt.Println(p1)

	schema := Schema{
		Users: make(map[string]User),
		Posts: make(map[string]Post),
	}

	schema.Users[u1.Username] = u1
	schema.Posts[p1.Heading] = p1

	fmt.Println(schema)

	// Now convert the data into JSON and print

	data, err := json.Marshal(schema)
	if err != nil {
		fmt.Println(err)
	}
	//fmt.Printf("%s", string(data))

	// Append data to exist JSON

	u2 := User{
		Username: "user2",
		Email:    "user2@example.com",
	}

	p2 := Post{
		Heading:     "Post 2 heading",
		Description: "Post 2 description",
	}

	schema.Users[u2.Username] = u2
	schema.Posts[p2.Heading] = p2

	data, err = json.Marshal(schema)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%s\n", data)

	// Assume like you have to do unmarshal to append
	// create empty schema to store the data
	schema2 := Schema{
		Users: make(map[string]User),
		Posts: make(map[string]Post),
	}
	// then unmarshal by saying to store there, go principle share the memory
	err = json.Unmarshal(data, &schema2)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("Read from schema 2 >>>>>> ", schema2)

	u3 := User{
		Username: "user3",
		Email:    "user3@example.com",
	}

	p3 := Post{
		Heading:     "Post 3 heading",
		Description: "Post 3 description",
	}

	schema2.Users[u3.Username] = u3
	schema2.Posts[p3.Heading] = p3

	data, err = json.Marshal(schema2)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("data from schema 2 >>>>>>> %s\n ", data)

	// Write JSON to file
	fileName := "./my.json"

	err = os.WriteFile(fileName, data, 0755)
	if err != nil {
		fmt.Println(err)
	}

	//Read JSON from file
	schema3 := Schema{
		Users: make(map[string]User),
		Posts: make(map[string]Post),
	}

	dataFromFile, err := os.ReadFile(fileName)
	if err != nil {
		fmt.Println(err)
	}

	err = json.Unmarshal(dataFromFile, &schema3)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("schema3 >>>>> ", schema3)

	// append data to structure
	u4 := User{
		Username: "user4",
		Email:    "user4@example.com",
	}

	p4 := Post{
		Heading:     "Post 4 heading",
		Description: "Post 4 description",
	}

	schema3.Users[u4.Username] = u4
	schema3.Posts[p4.Heading] = p4

	data, err = json.Marshal(schema3)
	if err != nil {
		fmt.Println(err)
	}

	// new data appended

	fmt.Printf("Schema4 >>>>> data %s\n", data)

	// now save changes to file
	os.WriteFile(fileName, data, 0755)
}