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

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

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)
}

Common `ToMap` method across structs [duplicate]

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())
}

why cannot use (type func(string)) as type func(interface{}) in assignment [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.
Please first have a look at the code below.
package main
import "fmt"
type InterfaceFunc func(interface{})
type StringFunc func(string)
func stringFunc(s string) {
fmt.Printf("%v", s)
}
func interfaceFunc(i interface{}) {
fmt.Printf("%v", i)
}
func main() {
var i = interfaceFunc
var s = stringFunc
i = s // I would like someone to explain why this can't be done exactly.
}
Run at https://play.golang.org/p/16cE4O3eb95
Why an InterfaceFunc can't hold a StringFunc while an interface{} can hold a string.
You can not do s = i or i = s, and the reason is both functions are of different type (different signatures), you can not just assign one type with another in golang.
Also type InterfaceFunc func(interface{}) type StringFunc func(string) are sitting there doing nothing.

Why does append not work with slices? [duplicate]

This question already has answers here:
Value receiver vs. pointer receiver
(3 answers)
My object is not updated even if I use the pointer to a type to update it
(3 answers)
Closed 9 months ago.
I cannot figure out why the following code is not working:
type Writer interface {
Write(input []byte) (int, error)
}
type resultReceiver struct {
body []byte
}
func (rr resultReceiver) Write(input []byte) (int, error) {
fmt.Printf("received '%s'\n", string(input))
rr.body = append(rr.body, input...)
fmt.Printf("rr.body = '%s'\n", string(rr.body))
return len(input), nil
}
func doWrite(w Writer) {
w.Write([]byte("foo"))
}
func main() {
receiver := resultReceiver{}
doWrite(receiver)
doWrite(receiver)
fmt.Printf("result = '%s'\n", string(receiver.body))
}
https://play.golang.org/p/pxbgM8QVYB
I would expect to receive the output:
received 'foo'
rr.body = 'foo'
received 'foo'
rr.body = 'foofoo'
result = 'foofoo'
By instead it is not setting the resultReceiver.body at all?
You are trying to change the underlying state of your resultReceiver which requires a pointer to the struct. You have a function instead of a method:
https://play.golang.org/p/zsF8mTtWpZ
Checkout Steve Fancia's talk on Go mistakes; Numbers 4 and 5, Functions vs Methods and Pointers vs Values respectively, will be a good refresher for you.
https://golang.org/doc/effective_go.html#pointers_vs_values
see Effective Go pointers vs values
by your way, the method to receive just a copy of the value

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!")
}

Resources