Allocless way to check interface compatibility
vbauerster opened this issue ยท 4 comments
Interfaces part shows a way to check interface compatibility (fulfillment):
type NullWriter struct {}
var _ io.Writer = &NullWriter{}
Nothing wrong with above code, but for completeness sake it worth mention that we needn't allocate a new variable since any value of type *NullWriter
will do, even nil:
type NullWriter struct {}
var _ io.Writer = (*NullWriter)(nil)
This explicit conversion works, because nil
is typed in Go. Check this playground example.
I see! Thank you so much for taking the time to point this out! ๐ I actually thought that the compiler would optimise the _
variable away, but I suppose not?
I will write up a pull request for this ๐ Sorry for the late reply!
@vbauerster I had a look at this, using the build flag go build -gcflags '-m -m' ./main.go
on the following code:
package main
import (
"io"
)
type NullWriter struct{}
func (writer *NullWriter) Write(b []byte) (int, error) {
return 0, nil
}
var _ io.Writer = (*NullWriter)(nil)
var _ io.Writer = &NullWriter{}
func main() {
var _ io.Writer = &NullWriter{}
var _ io.Writer = (*NullWriter)(nil)
return
}
This gave me the following output:
# command-line-arguments
./main.go:9:6: can inline (*NullWriter).Write as: method(*NullWriter) func([]byte) (int, error) { return 0, nil }
./main.go:16:6: can inline main as: func() { var _ io.Writer; _ = &NullWriter literal; var _ io.Writer; _ = (*NullWriter)(nil); return }
/var/folders/yk/2tnyv8g550zb0bg4vt0vn4l40000gn/T/go-build491024858/b001/_gomod_.go:6:6: can inline init.0 as: func() { keepalive_modinfo = __debug_modinfo__ }
./main.go:9:7: (*NullWriter).Write writer does not escape
./main.go:9:33: (*NullWriter).Write b does not escape
./main.go:17:20: main &NullWriter literal does not escape
./main.go:17:6: main &NullWriter literal does not escape
./main.go:18:6: main (*NullWriter)(nil) does not escape
This suggests that the compiler actually optimises the _
variables away. The output suggests that neither line 17 and 18 do not get allocated on the heap, and it seems to have completely ignored lines 13 and 14. So, I believe that there is no difference between the two methods?
Perhaps I am going about this all wrong though? If you have input on this, let me know, I would love to learn!
Thank you ๐
Frankly speaking I didn't think about _
part. But is sounds plausible that there is no difference because of compiler optimisation. So now I'm not sure if it worth mentioning the other way at all. ๐ค
Alright, I will keep the issue open, so that anyone can chime in and maybe give us a definitive answer on this ๐ Thanks again for opening the issue!