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

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.

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

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.

How to implement a generic slice appender? [duplicate]

This question already has answers here:
Appending to go lang slice using reflection
(2 answers)
Closed 8 months ago.
I'm relatively new to go. I'm trying to write a generic "appender" function. This is a simplification, but its an attempt to create a clean interface for processing some lists. Specifically, I have questions about the two errors that this generates:
package main
type GenericFunc func() *interface{}
func Append(ints interface{}, f GenericFunc) {
ints = append(ints, f())
}
func ReturnInt() *int {
i := 1
return &i
}
func main() {
var ints []*int
Append(ints, ReturnInt)
}
Playground
prog.go:5:18: first argument to append must be slice; have interface
{} prog.go:15:11: cannot use ReturnInt (type func() *int) as type
GenericFunc in argument to Append
Why can't ReturnInt be of type GenericFunc? If this doesn't work, I'm not understanding how interface{} can be used with functions at all.. can it?
How can you accept a "generic" slice and append to it using reflection? This would involve checking that GenericFunc returns the same type that the slice is, but after that appending should be possible.
The types func() *interface{} (type type of GenericFunc) and (type func() *int) (the type of ReturnInt) are different types. One returns a *interface{}. The other returns a *int. The types are not assignable to each other.
Use this function to generically append the result of a function to a slice:
func Append(sp interface{}, f interface{}) {
s := reflect.ValueOf(sp).Elem()
s.Set(reflect.Append(s, reflect.ValueOf(f).Call(nil)[0]))
}
Call it like this:
var ints []*int
Append(&ints, ReturnInt)
The function will panic if the argument is not a pointer to a slice or the function does not return a value assignable to a slice element.
playground example

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

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