Type of the M1, M2 and M3 fields are different, so without generics (Go 1.18) you can't have a function that have multiple return types, assignable to these different fields.
Before showing what's possible with older versions of Go (pre 1.18), let me tell you that I would not use them in production. They are inconvenient and slow (due to reflection). I would write helpers for different types and use those, or use a library that already has them, e.g. github.com/icza/gox (package gox) (disclosure: I'm the author).
And if Go 1.18 is allowed, I would use the generic solution shown at the end.
set() using reflection
What you can do is write a helper that gets the address of a field and the value you want to set for it (more precisely a pointer to it), and using reflection this is doable.
This is how this helper could look like:
func set(p, v interface{}) {
rv := reflect.ValueOf(v)
rp := reflect.New(rv.Type())
rp.Elem().Set(rv)
reflect.ValueOf(p).Elem().Set(rp)
}
Using it:
slice := []string{"abc", "def"}
var value X
set(&value.M1, time.Now().Unix())
set(&value.M2, "00000000-0000-0000-0000-000000000000")
set(&value.M3, slice)
fmt.Println(*value.M1, *value.M2, *value.M3)
This will output (try it on the Go Playground):
1257894000 00000000-0000-0000-0000-000000000000 [abc def]
ptr() using reflection and type assertion
Another, similarly inconvenient solution would be to write a single helper that returns a pointer to its argument using reflection:
func ptr(v interface{}) interface{} {
rv := reflect.ValueOf(v)
rp := reflect.New(rv.Type())
rp.Elem().Set(rv)
return rp.Interface()
}
The problem with this is that you have to use type assertion on the result:
value := X{
M1: ptr(time.Now().Unix()).(*int64),
M2: ptr("00000000-0000-0000-0000-000000000000").(*string),
M3: ptr(slice).(*[]string),
}
Try this one on the Go Playground.
Go 1.18 generic solution
If Go 1.18 will be allowed for you, a single helper is enough that uses no reflection:
func Ptr[T any](t T) *T {
return &t
}
And no type assertion is needed to use it:
value := X{
M1: Ptr(time.Now().Unix()),
M2: Ptr("00000000-0000-0000-0000-000000000000"),
M3: Ptr(slice),
}
Try this one on the Go Playground.
See related: How do I do a literal *int64 in Go?