Common `ToMap` method across structs [duplicate] - go

This question already has answers here:
Go embedded struct call child method instead parent method
(1 answer)
What is the idiomatic way in Go to create a complex hierarchy of structs?
(1 answer)
Ensuring embedded structs implement interface without introducing ambiguity
(2 answers)
Closed 3 years ago.
We have a few structs and we wanted to have a common ToMap method that converts the struct to Map. It does by marshaling and unmarshalling to json. But it does not seem to work.
Is it because the Mappable struct receives ToMap() and it does not have any member attributes?
If so, is there any way to make ToMap() to be received on Params struct instead of Mappable struct.
I've kept the code below but feel free to edit at https://play.golang.org/p/aDsYxddImxb too
package main
import (
"fmt"
"encoding/json"
)
type Mappable struct {}
func (m *Mappable) ToMap() (reqInterface map[string]interface{}) {
resJson, err := json.Marshal(m)
fmt.Println("**** err ****", err)
json.Unmarshal(resJson, &reqInterface)
return
}
type Params struct {
Mappable
A string `json:"a"`
B string `json:"b"`
C string `json:"c"`
D string `json:"d"`
}
func main() {
params := Params{
A: "dummy",
B: "dummy",
C: "dummy",
D: "dummy",
}
fmt.Printf("struct to convert: %#v \n", params)
fmt.Println("Converted with common ToMap method: ", params.ToMap())
}

Related

How to pass a slice of type A to a function that take a slice of interface that is implemented by A elegantly? [duplicate]

This question already has answers here:
Type converting slices of interfaces
(9 answers)
Cannot convert []string to []interface {}
(7 answers)
Cannot use args (type []string) as type []interface {} [duplicate]
(1 answer)
slice of struct != slice of interface it implements?
(6 answers)
Closed 7 days ago.
I have two types AssetClips and Videos that implement the interface call timelineClip.
I wanted to pass a []AssetClips or a []Videos to a function that take as argument a []timelineClip but the compiler was complaining, I don't really understand why. I ended up doing a for loop to convert my []AssetClips and my []Videos to []timelineClip
Is it necessary and is there a more elegant way of doing that?
// myFunctionThatTakesASliceOfTimelineClips(assetClips) is not possible
// myFunctionThatTakesASliceOfTimelineClips(videos) is not possible
var timelineClips []timelineClip
for _, assetClip := range assetClips {
timelineClips = append(timelineClips, assetClip)
}
for _, video := range videos {
timelineClips = append(timelineClips, video)
}
myFunctionThatTakesASliceOfTimelineClips(timelineClips)
It is necessary, and this is an elegant way to do it.
This is necessary because the mechanics of passing a slice of interface is different from the mechanics of passing a slice of structs. Each element of a slice of structs is a copy of the struct itself, whereas the elements of an interface is an interface pointing to an instance of a struct, together with its type.
If you want to avoid copying, you could use a generics for this. In short, you just change signature of
func myFunctionThatTakesASliceOfTimelineClips(timelineClips []timelineClip)
to
func myFunctionThatTakesASliceOfTimelineClips[T timelineClip](timelineClips []T)
As an example:
https://go.dev/play/p/FTj8rMYq9GF
package main
import "fmt"
type Exampler interface {
Example()
}
type A struct{}
type B struct{}
func (a A) Example() {
fmt.Println("it worked")
}
func (b B) Example() {
fmt.Println("it worked")
}
func DoExample[T Exampler](tt []T) {
for _, t := range tt {
t.Example()
}
}
func main() {
aa := []A{{}}
bb := []B{{}}
DoExample(aa)
DoExample(bb)
}

Why private members are not passed from Cadence activities? [duplicate]

This question already has answers here:
json.Marshal(struct) returns "{}"
(3 answers)
JSON and dealing with unexported fields
(2 answers)
(un)marshalling json golang not working
(3 answers)
Parsing JSON in Golang doesn't Populate Object [duplicate]
(1 answer)
Printing Empty Json as a result [duplicate]
(1 answer)
Closed 7 months ago.
I noticed that when I use a struct consisting of both public and private members, then the private ones are not copied(?) by Cadence activities.
For example I have a struct:
package foo
type Foo struct {
Name string
PublicList []string
privateList []string
}
func NewFoo() *Foo {
return &Foo{
Name: "Test",
PublicList: []string{"A", "B", "C"},
privateList: []string{"one", "two"},
}
}
func (f *Foo) ShowLists() {
fmt.Println("PublicList: ", f.PublicList, ", privateList: ", f.privateList)
}
I also use other struct, registered as activities struct:
package activities
type FooActivities struct{}
func (a *FooActivities) NewFoo(ctx context.Context) (*foo.Foo, error) {
return foo.NewFoo(), nil
}
func (a *FooActivities) ShowLists(ctx context.Context, f *foo.Foo) error {
f.ShowLists()
return nil
}
My workflow calls these two activities in a following way:
var f *foo.Foo
workflow.ExecuteActivity(ctx, fooActivities.NewFoo).Get(ctx, &f)
workflow.ExecuteActivity(ctx, fooActivities.ShowLists, f).Get(ctx, nil)
The result, printed by ShowLists function:
PublicList: [A B C] , privateList: []
Why is the private list not initialized as expected? Is this a bug or feature? I couldn't find answer for this question in the Cadence documentation.
Cadence (and Temporal) by default use json.Marshal to serialize and json.Unmarshall to deserialize activity arguments. It doesn't serialize private fields.
Here is a possible workaround.
I think it's cause by reflect cann't copy unexported field

Unmarshal into pointer vs value receiver feilds [duplicate]

This question already has answers here:
Difference using pointer in struct fields
(3 answers)
Closed 3 years ago.
I'm learning Golang recently. I know pointer and value receivers how it works generally.
When Unmarshal JSON string like follow 2 examples, I feel that first one (pointer receiver) more efficient way to use memory. But I have seen lots of examples and articles not uses this way. Is there any reason for this? And what are use cases for them?
package main
import (
"encoding/json"
"fmt"
)
type Outer struct {
ID int `json:"id"`
PointerValue *string `json:"pointer_str"`
Inner *Inner `json:"inner"`
}
type Inner struct {
Value string `json:"value"`
}
func main() {
testJson := `{
"id": 1,
"pointer_str": "example-value",
"inner": {
"value": "some-value"
}
}`
testStruct := &Outer{}
json.Unmarshal([]byte(testJson), testStruct)
fmt.Printf("%+v\n", testStruct)
fmt.Printf("%+v\n", *testStruct.PointerValue)
fmt.Printf("%+v\n", testStruct.Inner)
}
Output:
&{ID:1 PointerValue:0x40c250 Inner:0x40c258}
example-value
&{Value:some-value}
Or
package main
import (
"encoding/json"
"fmt"
)
type Outer struct {
ID int `json:"id"`
PointerValue string `json:"pointer_str"`
Inner Inner `json:"inner"`
}
type Inner struct {
Value string `json:"value"`
}
func main() {
testJson := `{
"id": 1,
"pointer_str": "example-value",
"inner": {
"value": "some-value"
}
}`
testStruct := &Outer{}
json.Unmarshal([]byte(testJson), testStruct)
fmt.Printf("%+v\n", testStruct)
fmt.Printf("%+v\n", testStruct.Inner)
}
Output:
&{ID:1 PointerValue:example-value Inner:{Value:some-value}}
{Value:some-value}
Updated: my meaning of efficiency was "efficient way to use memory"
The assumption that it is more efficient is wrong. The one without pointer is more efficient because there is no need for indirection and the value is in the memory cache along with the other values of Outer. Access will be faster.
Use a pointer when the Inner value is optional. It would have a nil value when the value is absent. Otherwise use the form without pointer. You would also use a pointer if the value of Inner in the JSON string may be null.

Is there a way to generically represent a group of similar functions? [duplicate]

This question already has answers here:
Type func with interface parameter incompatible error
(1 answer)
Func with interface argument not equals to func with string argument. Why?
(1 answer)
Go function types that return structs being used with interfaces
(2 answers)
Passing an arbitrary function as a parameter in Go
(4 answers)
How to convert from `func() *int` to `func() interface{}`? [duplicate]
(1 answer)
Closed 8 months ago.
package main
import "fmt"
type Pet interface {
Bark()
}
type Dog int
func (d Dog) Bark() {
fmt.Println("W! W! W!")
}
type Cat int
func (c Cat) Bark() {
fmt.Println("M! M! M!")
}
type AdoptFunc func(pet Pet)
func adoptDog(dog Dog) {
fmt.Println("You live in my house from now on!")
}
func adoptCat(cat Cat) {
fmt.Println("You live in my house from now on!")
}
func main() {
var adoptFuncs map[string]AdoptFunc
adoptFuncs["dog"] = adoptDog // cannot use adoptDog (type func(Dog)) as type AdoptFunc in assignment
adoptFuncs["cat"] = adoptCat // the same as above
}
As the code above, is there a way to use a map or array to collect a bunch of similar functions adoptXxx? If not, what is right pattern to use for this situation?
To use the map as a function collection you'll have to change the signature of your functions to match. func(Pet) is not the same type as func(Dog).
You can re-write AdoptXXX functions to take in Pet and do a type select to ensure correct pet is being input:
func adoptDog(pet Pet) {
if _, ok := pet.(Dog); !ok {
// process incorrect pet type
}
fmt.Println("You live in my house from now on!")
}

How to change the pointer of a variable in a struct with method implemented from interface [duplicate]

This question already has answers here:
My object is not updated even if I use the pointer to a type to update it
(3 answers)
X does not implement Y (... method has a pointer receiver)
(4 answers)
Closed 8 months ago.
Edit: For everyone suggesting using a pointer receiver in the function: By changing the method to have a pointer receiver, the structure no longer implements the interface. I have a image at the bottom of my question showing that.
I am trying to make a setter that will mutate the pointer of a variable in a struct with a method implemented from an interface.
package main
import "fmt"
func main() {
i := 1
b := BlahImpl {id:&i}
fmt.Println(b.ID())
j := 2
b.SetID(&j)
fmt.Println(b.ID())
}
type BlahInterface interface {
SetID(*int)
ID() int
}
type BlahImpl struct {
id *int
}
func (b BlahImpl) SetID(i *int) {
b.id = i
}
func (b BlahImpl) ID() int {
return *b.id
}
The current output is:
1
1
But I would like:
1
2
When I use pointer receiver I get this error because the struct is no longer implementing the interface.
Well, to be honest I do not quite get why it works this way, but this works as you want it to:
package main
import "fmt"
func main() {
i := 1
b := BlahImpl{id: &i}
fmt.Println(b.ID())
j := 2
b.SetID(&j)
fmt.Println(b.ID())
}
type BlahInterface interface {
SetID(*int)
ID() int
}
type BlahImpl struct {
id *int
}
func (b *BlahImpl) SetID(i *int) {
b.id = i
}
func (b *BlahImpl) ID() int {
return *b.id
}
The difference is how the structure's methods are defined. I've added * before the name so reference on the structure is passed into the method. It looks like without * the method gets copy of the struct so the modification does not work.

Resources