ncopiy
ncopiy

Reputation: 1604

Modify struct fields during instance generation

Foreign application API gives me a list of names in JSON format. I need modify all of those.
But I do not like to write some loop for it (especially after Python using with reflection and stuff)

Is there any method to write something like this in Go?

type MyIncredibleType struct {
    Name    ModifyName  // ModifyName is not a type!
} 

func ModifyName(input string) string {
    return input + ".com"
}

The expected behavior of this is:

a := MyIncredibleType{Name: "Abracadabra"}
print(a.Name) // Abracadabra.com

Upvotes: 1

Views: 600

Answers (2)

Zanicar
Zanicar

Reputation: 100

This seems pretty straight forward to me, assuming I understand your question correctly:

// ModifyName func
func ModifyName(input string) string {
    return fmt.Sprintf("%v.com", input)
}

If you wish to achieve this within the type itself, without modifying (mutating) the internal state:

type MyType sturct {
    name string // unexported
}

// accessor func to return name
func (t MyType) Name() string {
    return t.name
}

// accessor func to return modified name
func (t MyType) ModifiedName() string {
    return fmt.Sprintf("%v.com", t.name)
}

If you want to modify the internal state:

type MyType struct {
    name string
}

// mutator func (note the pointer for pass by reference)
func (t *MyType) ModifyName(input string) {
    t.name = fmt.Sprintf("%v.com", input)
}

// accessor (note no pointer for pass by value)
func (t MyType) Name() string {
    return t.name
}

Upvotes: 2

Himanshu
Himanshu

Reputation: 12675

This is is not possible in GO. That's not how struct works in Go.

type MyIncredibleType struct {
    Name    ModifyName `json:"name"`  // ModifyName is not a type!
}

you can only define Built-in types for your fields of struct or you can define Composite Literal types.

Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated. They consist of the type of the literal followed by a brace-bound list of elements. Each element may optionally be preceded by a corresponding key.

Try to create a method receiver of struct which you are using to parse json coming from the api to modify the name. That will let you achieve something similar to what you want.

package main

import (
    "fmt"
)

type MyIncredibleType struct {
    Name    string `json:"name"`  // ModifyName is not a type!
} 

func(myIncredibleType *MyIncredibleType) ModifyName() string {
    return myIncredibleType.Name+".com"
}

func main() {
    a := MyIncredibleType{Name: "Abracadabra"}
    name := a.ModifyName()
    fmt.Printf("%s",name)
}

Playground Example

Or you can pass an interface which will wrap any struct value with name field and then use Type assertion to get the underlying value to modify the same and return the result:

package main

import (
    "fmt"
)

type MyIncredibleType struct {
    Name    string `json:"name"`  // ModifyName is not a type!
} 

func ModifyName(input interface{}) string{
        return input.(interface{}).(string)+".com"
}

func main() {
    a := MyIncredibleType{Name: "Abracadabra"}
    name := ModifyName(a.Name)
    fmt.Printf("%s",name)
}

Working code on Go Playground

For more information also go through Golang method Declarations on how to create receivers.

Upvotes: 1

Related Questions