Interfaces and address operators - pointers

I have a problem to understand why the address operator can be used when the return type is an interface
func NewReader() IReader {
return &Reader{}
}
but (of course) not when a return type is a struct
func NewReader() Reader {
return &Reader{} // cannot use &Reader literal (type *Reader) as type Reader in return argument
}
The function signature later is func MyFuncReader(r IReader) but the reflect.TypeOf(r) is *main.Reader.
So the type IReader is hiding the fact that it is pointer?
The function signature func MyFuncReader(r IReader) doesn't tell me, that a pointer or a value was passed the func?
Samples
Full Sample with interface https://play.golang.org/p/1Db1Jybp0rP
Full Sample without interface https://play.golang.org/p/nPtu09yhe0C

If the return type of a function is an interface type, you may return any values that implement that interface. Spec: Return statements:
The return value or values may be explicitly listed in the "return" statement. Each expression must be single-valued and assignable to the corresponding element of the function's result type.
In your first example Reader has methods with pointer receiver, so only a pointer to Reader (that is *Reader) implements the IReader interface. So you have to return &Reader{}.
If your function has a return type of a concrete type, you have to return a value of that exact concrete type, you can't return a value of a pointer to that type.

When the return type is a Reader
func NewReader() Reader {
return &Reader{} // cannot use &Reader literal (type *Reader) as type Reader in return argument
}
you cannot use a pointer to a Reader type in place of a Reader type. The reason being they are just not of the same type.
When you use an interface like IReader as a return type as in
func NewReader() IReader {
return &Reader{}
}
it basically means that any type implementing the methods of the IReader interface will classify as a type implementing that interface and thus will be acceptable. Since the type *Reader implements the IReader type in your example, it is an acceptable return value of the NewReader function here. That means if I introduce a new type which implements this interface, such as,
type dummy int
func (d dummy) GetCount() int {
return d
}
func (d dummy) IncreaseCount() {
fmt.Println("Increased count: %d", d)
}
then I can do something like
func NewReader() IReader {
var d dummy
d = 5
return d
}
and it would still work. The underlying type of this returned value on checking using the reflect package will be dummy.

Related

Failure to discover property with reflection

Taking the following minimal example:
type IMyInterface =
interface
abstract member Name: string with get
end
let testInstance =
{ new IMyInterface with
member _.Name = "Hello Word" }
I would have naively expected a call to testInstance.GetType().GetProperties() to contain a PropertyInfo element corresponding to Name.
However, only an empty array is returned.
Using testInstance.GetType().GetProperty("Name") yields no better as it simply returns a <null> object.
More confusing still, Visual Studio 2022 IntelliSense lists Name as a valid property (as I'd expect).
How can I get a PropertyInfo corresponding to the Name property?
In F# all interface implementations are private. This means that interface methods and properties do not appear as methods and properties of the implementing class.
In C# this works a bit differently: if you define a public member that happens to match an interface member, you don't have to explicitly tell the compiler that it's meant to be the interface implementation, the compiler will map it to the interface automatically for you.
So, for example, if you write this:
class MyClass : IMyInterface {
public string Name { get; }
}
The C# compiler will actually compile it as this:
class MyClass : IMyInterface {
public string Name { get; }
string IMyInterface.Name { get { return this.Name; } }
}
(well, it's not exactly like that, but you get the idea)
But the F# compiler doesn't do that. If you want a class property in addition to the interface property, you have to roll one yourself:
type MyClass() =
member __.Name = "Hello Word"
interface IMyInterface with
member this.Name = this.Name
But if you just want the interface property, you can get it off of the interface type:
let nameProp = typeof<IMyInterface>.GetProperty("Name")
let helloWorld = nameProp.GetValue testInstance
Or, if you don't know the interface type in advance, you can get it from the object type as well:
let intf = testInstance.GetType().GetInterfaces().[0]
let nameProp = intf.GetProperty("Name")
let helloWorld = nameProp.GetValue testInstance

Pointer to an empty interface type assertion

I am receiving a pointer to an interface to my function, and I am trying to iterate over it. The underlying type is a string slice, which I can convert to it if I am using type interface{} and not a pointer to it *interface{} What is the best way to type assert pointer to interface? Using pointer because the value to be transformed is of huge size.
Code that doesn't work:
func convertMember(member *interface{}) {
for _, members := range member.([]string) {
invalid type assertion: member.([]string) (non-interface type *interface {} on left)
Code that doesn't work with dereferencing pointer:
func convertMember(member *interface{}) {
for _, members := range *member.([]string) {
invalid type assertion: member.([]string) (non-interface type *interface {} on left)
Code that works if I change the parent function to send an interface instead of its pointer:
func convertMember(member interface{}) {
for _, members := range member.([]string) {
Or should I type assert it to string slice and use a pointer to it?
You need to dereferencing before assertion:
func convertMember(member *interface{}) {
for _, members := range (*member).([]string) { ... }
}
But why do you want a pointer to interface? When a struct implements some interface, the pointer of that struct implements that interface too. So a pointer to interface is kind of never-need.
For your reference, here's a related question: Why can't I assign a *Struct to an *Interface?

Interfaces stored as value; Methods unable to update struct fields

I have a tool that I'm writing that exposes some functions that pull information out of a static database to several scripting languages that I'm embedding into the tool.
I thought; "Hey sounds like a nice use case for interfaces". So I defined an interface like so in my package scripting
type ScriptingLang interface {
RunScript(filename string) error
RunString(s string) error
Interpreter() error
Init() error
IsInit() bool
}
Then I store a map of them so I can look them up by a string defined like so in a different package.
var ScriptingLangs = make(map[string]scripting.ScriptingLang)
and a function to register them. Also some little helper functions like
func RunString(lang, s string) error {
if v, ok := ScriptingLangs[lang]; ok {
if !v.IsInit() {
v.Init()
}
return v.RunString(s)
} else {
return NoSuchLangErr
}
return nil
}
The problem that I ran into is it seams that interfaces can't have methods with pointer receivers. As a result my Lua struct that implements ScriptingLang isn't able to save it's *state because it's stored in ScriptingLangs.
I've tried updating the value stored in the map at the end of functions that save state and it didn't update the value.
To my understanding you shouldn't use pointers of interfaces so what are my options here? I would like to really keep the interfaces so I can do some neat stuff with git submodules.
A minimal example of my problem:
package main
import (
"fmt"
)
type ScriptingLang interface {
DoString(s string) error
Init() error
}
type Lua struct {
state string
}
func (l Lua) DoString(s string) error {
fmt.Printf("Doing '%v' with state '%v'\n", s, l.state)
return nil
}
func (l Lua) Init() error {
l.state = "Inited"
return nil
}
var lang ScriptingLang
func main() {
lang = Lua{}
lang.Init()
lang.DoString("Stuff")
}
If you want to mutate state, you need a pointer receiver, and your Init method doesn't have one. The fact that you're storing the value inside an interface makes no difference.
In your minimal(-ish) example, change the Init method (and any method that updates state) to have a pointer receiver, and point a pointer inside the interface and everything works:
func (l *Lua) Init() error {
l.state = "Inited"
return nil
}
...
func main() {
lang = &Lua{}
lang.Init()
lang.DoString("Stuff")
}
This article might help: http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go

Why a pointer needs to be returned when the return type is actually error?

I am reading the article Error handling and Go, and don't quite understand why a pointer (&errorString{text}) has to be returned when the return type is actually error?
My understanding is error is an interface, and errorString implements the interface, therefore, return errorString is also okay (but it is not the case).
// New returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
errorString implementation
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
Because error interface for errorString is implemented for a pointer (func (e *errorString) Error()), if it was implemented like below you would return the value directly:
func (e errorString) Error() string {
return e.s
}

map[Task]int64 where Task is an interface

Let's say I define the following interface in a Go library:
type Task interface {
Do() error
}
func Register(task Task) { ... }
func GetId(task Task) int64 { ... }
In Register(), the library associates a unique int64 with each task instance. GetId() must return the identifier for the given task.
My initial idea was to store the association as a map[Task]int64. This seems to work fine, but I was told that it would break if an object implementing Task was not equality-comparable (for example, a struct containing a map). I still need to check if this is true.
I was going to try and use a slice of struct { task Task; id int64 } instead and just iterate over it, but that would still require equality comparable Task instances. And AFAIU there is no identity comparison in Go.
How can I have a robust mapping from Task instances to their ID?
EDIT: Both solutions proposed so far work, but they have the disadvantage that every Task implementation has to include some repetitive code to handle the IDs. I could provide that code in a TaskBase struct that could be embedded, but ideally I would prefer a solution that doesn't require implementations to even know about the IDs (they are internal to the library and have no meaning outside of it).
A more complete example: http://play.golang.org/p/1RzDiw7F9t
package main
import (
"fmt"
"math/rand"
)
type Task interface {
Do() error
ID() int64
}
type XTask struct {
id int64
// other stuff
}
func NewXTask( /*task parameters...*/) *XTask {
t := &XTask{ /*initialize members*/}
t.id = Register(t)
// possibly more initialization...
return t
}
func (t *XTask) Do() error { return nil } // stub
func (t *XTask) ID() int64 { return t.id }
var taskRegistry = map[int64]Task{}
func Register(t Task) int64 {
var id int64
for {
id = rand.Int63()
if _, exists := taskRegistry[id]; !exists {
break
}
}
taskRegistry[id] = t
return id
}
func main() {
t1 := NewXTask()
t2 := NewXTask()
fmt.Printf("%x\n", t1.ID())
fmt.Printf("%x\n", t2.ID())
}
I used an ID method as Daniel suggested, and I turned the map backwards from the way you had it. This is because the Task objects know their own ID, so a map from Task to ID is not needed. A map from ID to task however, is useful for guaranteeing uniqueness. It might come in handy some other time if you find yourself with only an ID and you need the corresponding Task object.
Also note this example is not goroutine-safe. If you need that you will have to add synchronization.

Resources