Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get struct field tag using Go reflect package

Is it possible to reflect on a field of a struct, and get a reference to its tag values?

For example:

type User struct {
    name    string `json:name-field`
    age     int
}
// ...
user := &User{"John Doe The Fourth", 20}
getStructTag(user.name)
// ...
func getStructTag(i interface{}) string{
   //get tag from field
   
}

From what I can see, the usual way to do this is to range over typ.NumField(), and then call field.Tag.Get("tagname").

However, in my use-case, it would be much better to not have to pass the whole struct in.

like image 392
Jameo Avatar asked May 07 '14 01:05

Jameo


People also ask

How do you access a field in a struct in Go?

Go struct access fields The struct fields are accessed with the dot operator. We create an empty User struct. We initialize the fields with values and read them using the dot operator.

What is struct tag in Golang?

A struct is a user-defined type that contains a collection of fields. It is used to group related data to form a single unit. A Go struct can be compared to a lightweight class without the inheritance feature. A struct tag is additional meta data information inserted into struct fields.

What is a struct tag?

An optional identifier, called a "tag," gives the name of the structure type and can be used in subsequent references to the structure type. A variable of that structure type holds the entire sequence defined by that type.


3 Answers

You don't need to pass in the whole struct, but passing in the value of one of the fields is not sufficient.

In your example user.name field is just a string - the reflect package will have no way of correlating that back to the original struct.

Instead, you need to pass around the reflect.StructField for the given field:

field, ok := reflect.TypeOf(user).Elem().FieldByName("name")
…
tag = string(field.Tag)

Note: we use Elem above because user is a pointer to a struct.

You can play with an example here.

like image 182
djd Avatar answered Oct 12 '22 05:10

djd


Modifying the above answer can give value of a specific tag

package main

import (
    "fmt"
    "reflect"
)

type User struct {
    Name string `json:"name_field"`
    Age  int
}

func main() {
    user := &User{"John Doe The Fourth", 20}

    field, ok := reflect.TypeOf(user).Elem().FieldByName("Name")
    if !ok {
        panic("Field not found")
    }
    fmt.Println(getStructTag(field, "json")) //name_field
}

func getStructTag(f reflect.StructField, tagName string) string {
    return string(f.Tag.Get(tagName))
}

https://play.golang.org/p/Sb0i7za5Uow

like image 36
Raj Nandan Sharma Avatar answered Oct 12 '22 03:10

Raj Nandan Sharma


Clean way to list all tags from a struct (using external lib).

External lib: https://github.com/fatih/structs

Example: https://go.dev/play/p/C_yXMdbFYAq

package main

import (
    "fmt"

    "github.com/fatih/structs"
)

type User struct {
    Name string `json:"name_field"`
    Age  int    `json:"age_field"`
}

func main() {
    user := &User{}
    fields := structs.Fields(user)

    for _, field := range fields {
        tag := field.Tag("json")
        fmt.Println(tag)
    }
}

Result:

name_field
age_field
like image 1
Ady Junior Avatar answered Oct 12 '22 04:10

Ady Junior