Page Content

Tutorials

What Is Mean By Struct Tags In GoLang With Code Examples

Effective programming is made possible by Go’s type system and data structures, such as struct tags, which give struct fields metadata and provide a potent means of personalising the way data is treated, particularly during serialisation and deserialization.

What are Struct Tags in GoLang?

Struct tags are little bits of information that are affixed to a structure’s fields. They are annotations made up of brief strings linked to appropriate values that follow the type in a Go struct declaration. The way your code works is unaffected by structure tags unless other Go code is specially developed to analyse and use them at runtime.

Usually, they are formatted as key:"value" and wrapped in backticks `. Because they eliminate the need to use backslashes to escape quotation marks, raw string literals (with backticks) are preferable for tags because they are easier to read.

Advanced Struct Tag Usage

Struct tags are widely used in Go programming, for as in the encoding/json package from the standard library. It gives you the ability to specify the names, omissions, and disregards of struct fields while encoding (marshalling) Go structs into JSON and vice versa for decoding (unmarshaling).

In order to be “exported” and visible to the json package, Go fields meant for JSON encoding are customarily required to begin with an uppercase letter.

Customizing Field Names

Go’s json encoder automatically changes exported Go struct field names, which are normally CamelCase, to camelCase in JSON. However, you can use a json:”name” tag to specifically describe the JSON key name. This is very helpful when working with systems that use naming conventions like snake_case.

Code Example:

package main
import (
	"encoding/json"
	"fmt"
	"log"
)
type Location struct {
	Latitude  float64 `json:"latitude"`  // Customizes 'Latitude' to 'latitude' in JSON
	Longitude float64 `json:"longitude"` // Customizes 'Longitude' to 'longitude' in JSON
}
func main() {
	curiosity := Location{Latitude: -4.5895, Longitude: 137.4417}
	
	// Marshal the struct into JSON
	bytes, err := json.MarshalIndent(curiosity, "", "  ") // MarshalIndent for pretty printing
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(bytes))
}

Output

{
  "latitude": -4.5895,
  "longitude": 137.4417
}

This example uses the default Latitude and Longitude properties from the Location struct, but specifically maps them to latitude and longitude in the JSON output, respectively.

Omitting Empty Fields ()

If a struct tag’s omitempty option contains the zero value for its type (for example, 0 for numbers, “” for texts, false for booleans, or nil for pointers or slices), the json encoder is told to skip the field.

Code Example:

package main
import (
	"encoding/json"
	"fmt"
	"log"
)
type Product struct {
	Name        string `json:"productName"`
	Price       float64 `json:"price"`
	Description string `json:"description,omitempty"` // Omit if Description is empty
}
func main() {
	// Product with a description
	item1 := Product{Name: "Laptop", Price: 1200.00, Description: "High-performance computing"}
	bytes1, err := json.MarshalIndent(item1, "", "  ")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Item 1 (with description):\n", string(bytes1))
	fmt.Println("---")
	// Product without a description (Description field will be omitted)
	item2 := Product{Name: "Mouse", Price: 25.00}
	bytes2, err := json.MarshalIndent(item2, "", "  ")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Item 2 (without description):\n", string(bytes2))
}

Output

Item 1 (with description):
 {
  "productName": "Laptop",
  "price": 1200,
  "description": "High-performance computing"
}
---
Item 2 (without description):
 {
  "productName": "Mouse",
  "price": 25
}

As can be observed in item 2, the omitempty tag was applied, and as a result, the Description field is not included in the JSON output because its value is the zero value for a string (“”).

Ignoring Fields ()

By utilizing the special json:”-” tag, you can completely stop a field from being marshalled into JSON. For private information (such as passwords) or internal fields that shouldn’t be seen in the JSON output, this is helpful.

Code Example:

package main
import (
	"encoding/json"
	"fmt"
	"log"
	"time"
)
type User struct {
	Username  string    `json:"username"`
	Password  string    `json:"-"` // This field will be ignored
	Email     string    `json:"email"`
	CreatedAt time.Time `json:"createdAt"`
}
func main() {
	user := User{
		Username:  "sammy_shark",
		Password:  "superSecretPassword123", // This will not appear in JSON
		Email:     "sammy@example.com",
		CreatedAt: time.Now(),
	}
	bytes, err := json.MarshalIndent(user, "", "  ")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(bytes))
}

Output

{
  "username": "sammy_shark",
  "email": "sammy@example.com",
  "createdAt": "2025-09-06T13:31:00.227135982Z"
}

Because of the json:”-” tag, you can see that the Password field is totally missing from the JSON output.

Multiple Tags for Different Packages

A struct field may have more than one tag, each of which may be associated with a distinct package or function. This is formatted as key1:"value1" and key2:"value2".

Code Example:

package main
import (
	"encoding/json"
	"encoding/xml" // Assuming XML package is also used for serialization
	"fmt"
	"log"
)
type ProductInfo struct {
	Name  string  `json:"product_name" xml:"product_name"` // Custom name for both JSON and XML
	Price float64 `json:"item_price" xml:"item_price"`
}
func main() {
	product := ProductInfo{Name: "Go Book", Price: 39.99}
	// Marshal to JSON
	jsonBytes, err := json.MarshalIndent(product, "", "  ")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("JSON Output:\n", string(jsonBytes))
	fmt.Println("---")
	// Marshal to XML
	xmlBytes, err := xml.MarshalIndent(product, "", "  ")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("XML Output:\n", string(xmlBytes))
}

Output

JSON Output:
 {
  "product_name": "Go Book",
  "item_price": 39.99
}
---
XML Output:
 <ProductInfo>
  <product_name>Go Book</product_name>
  <item_price>39.99</item_price>
</ProductInfo>

Consistent naming across various serialization forms is made possible by the Name and Price fields’ tags for both JSON and XML packages.

Although omitempty and “-” are standard standards used by many packages, it’s crucial to keep in mind that how they behave varies depending on how the package processing the struct tags is implemented. The documentation for any third-party package that employs struct tags should therefore always be consulted.

You can also read What Is Build Tags In GoLang, Use Cases And How It Works

Agarapu Geetha
Agarapu Geetha
My name is Agarapu Geetha, a B.Com graduate with a strong passion for technology and innovation. I work as a content writer at Govindhtech, where I dedicate myself to exploring and publishing the latest updates in the world of tech.
Index