Why does append not work with slices? [duplicate] - go

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

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

I don't understand when to use pointers on go [duplicate]

This question already has answers here:
Pointers vs. values in parameters and return values
(5 answers)
When to use pointers [duplicate]
(1 answer)
Difference between returning a pointer and a value in initialization methods [duplicate]
(1 answer)
Why should constructor of Go return address?
(2 answers)
Why should I use a pointer ( performance)?
(3 answers)
Closed 1 year ago.
I am doing a tour of go language, and I have a question about pointers.
Example code (https://tour.golang.org/methods/19):
package main
import (
"fmt"
"time"
)
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
}
In this case it is using *MyError and &MyError, but I try to remove the * and & and it works correctly. Why are they using pointers in this example? What is the difference with normal variables? When should I use pointers or not?
"When should I use pointers?" is a very large question without a simple answer. Pointers are a way of passing a reference to a value, rather than a value itself, around, allowing you to modify the original value or "see" modifications to that value. It also prevents copying, which can be a performance improvement in very limited circumstances (do not pass pointers around all the time because it might be a performance improvement). Finally, pointers also let you represent "nothingness", which each pointer being able to be nil. This is both a blessing and a curse as you must check if each pointer is nil before accessing it, though.
In your specific example, the reason why returning &MyError works is because your Error() function operates on a value of *MyError (a pointer to MyError), rather than on a value of MyError itself. This means that *MyError implements the Error interface and is thus assignable to the error type, and so it can be returned from any function that expects an error as a return value.
Returning MyError wouldn't work on its own because MyError is not a *MyError. Go does some helpful things when dealing with function receivers: It will let you call any method on a MyError or *MyError if the receiver is *MyError, but it will only let you call methods on a *MyError if the type is *MyError - That is, Go will not "create" a pointer for you out of thin air.
If you were to remove * from func (e* MyError), you would be telling Go that Error() works on any instance of a MyError, which means that both *MyError and MyError would fulfill that contract. That's why both of the following are valid when you don't use a pointer receiver:
func (e MyError) Error() string {}
var _ error = MyError{} // Valid
var _ error = &MyError {}
In this particular case, using pointers will not make a difference. Here's one way to look at it:
In Go, all variables are passed by value. That means:
type T struct {...}
func f(value T) {..}
f(t)
Above, t is passed as value. That means when f is called, the compiler creates a copy of t and passed that to f. Any modifications f makes to that copy will not affect the t used to call f.
If you use pointers:
func f(value *T) {...}
f(&t)
Above, the compiler will create a pointer pointing to t, and pass a copy of that to f. If f makes changes to value, those changes will be made on the instance of t used to call f. In other words:
type T struct {
x int
}
func f(value T) {
value.x=1
}
func main() {
t:=T{}
f(t)
fmt.Println(t.x)
}
This will print 0, because the modifications made by f is done on a copy of t.
func f(value *T) {
value.x=1
}
func main() {
t:=T{}
f(&t)
fmt.Println(t.x)
}
Above, it will print 1, because the call to f changes t.
Same idea applies to methods and receivers:
type T struct {
x int
}
func (t T) f() {
t.x=1
}
func main() {
t:=T{}
t.f()
fmt.Println(t.x)
}
Above program will print 0, because the method modifies a copy of t.
func (t *T) f() {
t.x=1
}
func main() {
t:=T{}
t.f()
fmt.Println(t.x)
}
Above program will print 1, because the receiver of the method is declared with a pointer, and calling t.f() is equivalent to f(&t).
So, use pointers when passing arguments or when declaring methods if you want to modify the object, or if copying the object would be too expensive.
This is only a small part of the story about pointer arguments.

Make persistent changes to struct fields *and* satisfy the Writer interface? [duplicate]

This question already has answers here:
X does not implement Y (... method has a pointer receiver)
(4 answers)
Closed 4 years ago.
In order to actually change struct fields in a method, you need a pointer-type receiver. I understand that.
Why can't I satisfy the io.Writer interface with a pointer receiver so that I can make changes to struct fields? Is there an idiomatic way to do this?
// CountWriter is a type representing a writer that also counts
type CountWriter struct {
Count int
Output io.Writer
}
func (cw *CountWriter) Write(p []byte) (int, error) {
cw.Count++
return cw.Output.Write(p)
}
func takeAWriter(w io.Writer) {
w.Write([]byte("Testing"))
}
func main() {
boo := CountWriter{0, os.Stdout}
boo.Write([]byte("Hello\n"))
fmt.Printf("Count is incremented: %d", boo.Count)
takeAWriter(boo)
}
The code yields this error:
prog.go:27:13: cannot use boo (type CountWriter) as type io.Writer in argument to takeAWriter:
CountWriter does not implement io.Writer (Write method has pointer receiver)
It seems you can either satisfy the Writer interface or have your changes made to the actual struct. If I change the Write method to a value receiver (func (cw CountWriter) Write...), I can avoid the error but the value does not increment. :(
https://play.golang.org/p/pEUwwTj0zrb
boo Doesn’t implement the interface because Write takes *CountWriter and not a CountWriter
However, &boo will be accepted by Write, so you have to pass it instead.

In Go, how do I pass a slice of interface to something that expects slice of a different compatible interface? [duplicate]

This question already has answers here:
Type converting slices of interfaces
(9 answers)
Closed 6 years ago.
I have two interfaces, A and B. It happens that A includes B. Finally, I have a concrete implementation of A (call it Impl), which, by definition, also implements B.
For example:
type A interface {
Close() error
Read(b []byte) (int, error)
}
type Impl struct {}
func (I Impl) Read(b []byte) (int, error) {
fmt.Println("In read!")
return 10, nil
}
func (I Impl) Close() error {
fmt.Println("I am here!")
return nil
}
Since A requires Read(), and Impl implements A, it also satisfies io.Reader.
If I try to pass individual items across functions, it works fine. But if I try slices of A to functions expecting io.Reader, it fails.
Example:
func single(r io.Reader) {
fmt.Println("in single")
}
func slice(r []io.Reader) {
fmt.Println("in slice")
}
im := &Impl{}
// works
single(im)
// FAILS!
list := []A{t}
slice(list)
If I can pass an A to single(r io.Reader), why can I not pass []A to slice(r []io.Reader), and how would I correct it?
Actual implementation at https://play.golang.org/p/QOREQJTQhD just uncomment the last two lines in main() and the error shows:
main.go:38: cannot use list (type []A) as type []io.Reader in argument to slice
I kind of asked something similar here
In Go, how can I make a generic function with slices?
Sadly, this is definitely a weakness in Go. The only way for you to go around this is to make a new slice of type []io.Reader with elements from []A

Resources