Welcome To Golang By Example

Pretty print struct variables in Go (Golang)

Note: If you are interested in learning Golang, then for that we have a golang comprehensive tutorial series. Do check it out – Golang Comprehensive Tutorial Series. Now let’s see the current tutorial. Below is the table of contents.

Overview

There are two ways to print all struct variables including all its key and values.

Let’s say we have an employee struct as below:

type employee struct {
    name   string
    age    int
    salary int
}

Let’s see the two ways in which we can print the instance of the employee struct.

Using the fmt package

fmt.Printf() function can be used to print a struct.  Different format identifiers can be used to print a struct in different ways. Let’s see how different format identifiers can be used to print a struct in different formats.

Let’s first create an instance of employee

emp := employee{name: "Sam", age: 31, salary: 2000}
fmt.Printf("%v", emp)  -  {Sam 31 2000}
fmt.Printf("%+v", emp) - {name:Sam age:31 salary:2000}
fmt.Printf("%#v", emp) - main.employee{name:"Sam", age:31, salary:2000}

fmt.Println() function can also be used to print a struct. Since %v is the default for fmt.Printlin() function, hence output will be same as using %v for fmt.Printf()

fmt.Println(emp) - {Sam 31 2000}

Let’s see a working program too

package main

import "fmt"

type employee struct {
    name   string
    age    int
    salary int
}

func main() {
    emp := employee{name: "Sam", age: 31, salary: 2000}
    fmt.Printf("Emp: %v\n", emp)
    fmt.Printf("Emp: %+v\n", emp)
    fmt.Printf("Emp: %#v\n", emp)
    fmt.Println(emp)
}

Output

Emp: {Sam 31 2000}
Emp: {name:Sam age:31 salary:2000}
Emp: main.employee{name:"Sam", age:31, salary:2000}
{Sam 31 2000}

Printing the struct in JSON form

Second method is to print the struct in the JSON format. Marshal and MarshalIndent function of encoding/json package can be used to print a struct in JSON format. Here is the difference

Marshal(v interface{}) ([]byte, error)
MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

It is to be noted that both Marshal and MarshalIndent function can only access the exported fields of a struct, which means that only the capitalized fields can be accessed and encoded in JSON form.

package main

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

type employee struct {
    Name   string
    Age    int
    salary int
}

func main() {
    emp := employee{Name: "Sam", Age: 31, salary: 2000}
    //Marshal
    empJSON, err := json.Marshal(emp)
    if err != nil {
        log.Fatalf(err.Error())
    }
    fmt.Printf("Marshal funnction output %s\n", string(empJSON))

    //MarshalIndent
    empJSON, err = json.MarshalIndent(emp, "", "  ")
    if err != nil {
        log.Fatalf(err.Error())
    }
    fmt.Printf("MarshalIndent funnction output %s\n", string(empJSON))
}

Output:

Marshal funnction output {"Name":"Sam","Age":31}

MarshalIndent funnction output {
  "Name": "Sam",
  "Age": 31
}

The salary field is not printed in the output because it begins with a lowercase letter and is not exported. The Marshal function output is not formatted while the MarshalIndent function output is formatted.

golang also allows the JSON encoded struct key name to be different by the use of struct meta fields. Let’s first understand what is struct meta fields. A struct in go also allows adding metadata to its fields. These meta fields can be used to encode decode into different forms, doing some forms of validations on struct fields, etc. So basically any meta information can be stored with fields of a struct and can be used by any package or library for different purposes.

Below is the format for attaching a meta-data. Meta-data is a string literal i.e it is enclosed in backquotes

type strutName struct{
   fieldName type `key:value key2:value2`
}

Now for our use case, we will add JSON tags to employee struct as below. Marshal function will use the key name specified in the tags

type employee struct {
    Name   string `json:"n"`
    Age    int    `json:"a"`
    Salary int    `json:"s"`
}

Let’s see full program

package main

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

type employee struct {
    Name   string `json:"n"`
    Age    int    `json:"a"`
    Salary int    `json:"s"`
}

func main() {
    emp := employee{Name: "Sam", Age: 31, Salary: 2000}
    //Converting to jsonn
    empJSON, err := json.MarshalIndent(emp, '', '  ')
    if err != nil {
        log.Fatalf(err.Error())
    }
    fmt.Println(string(empJSON))
}

Output:

{
  "n": "Sam",
  "a": 31,
  "s": 2000
}

The key name in the output is the same as specified in the JSON meta tags.

Printing nested struct

Even if the struct contains another struct , same method as discussed above can be used to print the same

package main

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

type address struct {
    City    string `json:"city"`
    Country string `json:"country"`
}

type employee struct {
    Name    string  `json:"name"`
    Age     int     `json:"age"`
    Salary  int     `json:"salary"`
    Address address `json:"address"`
}

func main() {
    address := address{City: "some_city", Country: "some_country"}
    emp := employee{Name: "Sam", Age: 31, Salary: 2000, Address: address}
    //Converting to json
    empJSON, err := json.MarshalIndent(emp, "", "  ")
    if err != nil {
        log.Fatalf(err.Error())
    }
    fmt.Printf("MarshalIndent funnction output\n %s\n", string(empJSON))
}

Output

MarshalIndent function output
 {
  "name": "Sam",
  "age": 31,
  "salary": 2000,
  "address": {
    "city": "some_city",
    "country": "some_country"
  }
}

This is all about printing a struct. I hope you have liked this article. Please share the feedback in the comments.