Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Interface Field Values From an Interface Without Declaring Structure in Golang

I am trying to get field values from an interface in Golang. The interface is initially an empty interface which is getting its values from a database result. The DB query is working fine.

The only thing I need is that I need to get the field value of the interface. Here is my code:

s := reflect.ValueOf(t)
    for i := 0; i < s.Len(); i++ {
        fmt.Println(s.Index(i))
    }

where t is an interface having following values:

map[id:null count:1]

I want value of "count" like simply 1.

My problem is that the Index() method is returning a panic because it needs a struct and I dont have any struct here. So what should I do to get interface value? Is there any solution to iterate over an interface to get field values with or without Golang's reflection package?

Edit

After getting the value for count I need to parse it to json.

Here is my code:

type ResponseControllerList struct{
    Code            int             `json:"code"`
    ApiStatus       int             `json:"api_status"`
    Message         string          `json:"message"`
    Data            interface{}     `json:"data,omitempty"`
    TotalRecord     interface{}     `json:"total_record,omitempty"`
}
response := ResponseControllerList{}
ratingsCount := reflect.ValueOf(ratingsCountInterface).MapIndex(reflect.ValueOf("count"))
fmt.Println(ratingsCount)

response = ResponseControllerList{
                200,
                1,
                "success",
                nil,
                ratingsCount,
            }
GetResponseList(c, response)

func GetResponseList(c *gin.Context, response ResponseControllerList) {
    c.JSON(200, gin.H{
        "response": response,
    })
}

The above code is being used to get the ratingCount in JSON format to use this response as API response. In this code, I am using the GIN framework to make HTTP request to API.

Now the problem is that when I am printing the variable ratingsCount, its displaying the exact value of count in terminal what I need. But when I am passing it to JSON, the same variable gives me the response like:

{
    "response": {
        "code": 200,
        "api_status": 1,
        "message": "Success",
        "total_record": {
            "flag": 148
        }
    }
}

What is the way to get the count's actual value in JSON ?

like image 757
Amandeep kaur Avatar asked Sep 27 '17 11:09

Amandeep kaur


People also ask

CAN interface have fields in GoLang?

You put a set of methods into an interface, but you are unable to specify any fields that would be required on anything that implements that interface.

What does interface {} mean in GoLang?

interface{} means you can put value of any type, including your own custom type. All types in Go satisfy an empty interface ( interface{} is an empty interface). In your example, Msg field can have value of any type.

What is difference between struct and interface in GoLang?

Structs and interfaces are Go's way of organizing methods and data handling. Where structs define the fields of an object, like a Person's first and last name. The interfaces define the methods; e.g. formatting and returning a Person's full name.

How do you declare an interface variable in GoLang?

Declaring Interface Types Interface describes all the methods of a method set and provides the signatures for each method. To create interface use interface keyword, followed by curly braces containing a list of method names, along with any parameters or return values the methods are expected to have.

Can we create a variable of an interface type in Golang?

But you are allowed to create a variable of an interface type and this variable can be assigned with a concrete type value that has the methods the interface requires. Or in other words, the interface is a collection of methods as well as it is a custom type. To read more about Interfaces, please refer to the article Interface in Golang

How to declare an interface in Go language?

Declaring an interface in GoLang An interface is declared as a type. Here is the declaration that is used to declare an interface. type interfaceName interface {}

What interface does now mystring implement in Golang?

Now MyString is said to implement the interface VowelsFinder. This is quite different from other languages like Java where a class has to explicitly state that it implements an interface using the implements keyword. This is not needed in Go and Go interfaces are implemented implicitly if a type contains all the methods declared in the interface.

What is type switch in Golang?

Type Switch: In Go interface, type switch is used to compare the concrete type of an interface with the multiple types provide in the case statements. It is similar to type assertion with only one difference, i.e, case specifies types, not the values. You can also compare a type to the interface type.


2 Answers

You can use type assertion instead of reflection. It is generally better to avoid reflection whenever you can.

m, ok := t.(map[string]interface{})
if !ok {
    return fmt.Errorf("want type map[string]interface{};  got %T", t)
}
for k, v := range m {
    fmt.Println(k, "=>", v)
}

If you really want to use reflection, you can do something like this:

s := reflect.ValueOf(t)
for _, k := range s.MapKeys() {
    fmt.Println(s.MapIndex(k))
}

Update to reply to your latest update

It does not return what you expect because it returns a reflect.Value. If you want an integer value, you have to use ratingsCount.Int().

But as I said before, don't use reflection. Use the first solution with type assertion and just get the count with m["count"].

I posted working example there using type assertion: https://play.golang.org/p/9gzwtJIfd7

like image 153
R3v4n Avatar answered Oct 19 '22 20:10

R3v4n


This is my solution

type Header struct {
    Token string
}
    
type Request struct {
    Header 
}   


func requestedToken(request interface{}) string {
    requestValue := reflect.ValueOf(request)
    header := requestValue.FieldByName("Header")
    if header.Kind() == 0 {
        return ""
    }
    token := header.FieldByName("Token")
    if token.Kind() == 0 {
        return ""
    }
    return token.String()
}
like image 1
Châu Văn Khánh Nhật Avatar answered Oct 19 '22 21:10

Châu Văn Khánh Nhật