b := new(Blob)
var c Component = b
> Oh, so an interface is _already_ a pointer to a struct.
No, that's not the right way to look at it. In addition to Rob's
"interfaces are not pointers" message in the other thread, interfaces
can contain lots of different types, including pointers to structs,
direct structs, ints, bools, strings, maps, etc. The principle of an
interface concerns the methods attached to a type T, not what type T
is.
Dave.
No, it's a case of you don't understand the semantics.
That's an important distinction.
> In every other language I've used you have distinct types:
> - primitive
> - pointer
>
> They are not compatible.
A pointer is one kind of type.
A struct is another kind of type.
An integer is another kind of type.
A floating point number is another kind of type.
A boolean is another kind of type.
All of these types can have methods defined on them.
An interface type is defined by a set of methods.
Any value that implements the methods can be
assigned to an interface value of that type.
Like David said, an interface value is like a box
in which you can store any value that has the
necessary methods.
If a pointer type implements the methods,
you can store a value of that type in the interface value.
If a struct type implements the methods,
you can store a value of that type in the interface value.
If an integer type implements the methods,
you can store a value of that type in the interface value.
If a floating point type implements the methods,
you can store a value of that type in the interface value.
If a boolean type implements the methods,
you can store a value of that type in the interface value.
> But it doesn't change the fact that a * type object has just been
> converted into a primitive.
A value of pointer type has been stored into an interface value.
Calls to methods on that interface value will use that pointer
value as the receiver argument.
If you replace pointer by integer in that last paragraph, it still
works. Same for floating point, boolean, struct (and map, channel,
and function, but I've been ignoring those).
var p *int
var i int
var f float64
var b bool
var x interface{}
x = p
println(p == x.(*int))
x = i
println(i == x.(int))
x = f
println(f == x.(float64))
x = b
println(b == x.(bool))
Russ
I see. So it's just a case of strange syntax.
In every other language I've used you have distinct types:
- primitive
- pointer
They are not compatible.
Attempting to do either of these should yield an error:
- primitive x = pointer y
- pointer x = primitive y
Interfaces are strange.
var a *StructA = ...
var b InterfaceA = b
may be shorthand for:
b.setMyInnerInterfaceReferenceToObject(b)
But it doesn't change the fact that a * type object has just been
converted into a primitive.
This is counter intuitive.
you can't do this in general.
> I mean, technically I can do this right?
> package main
> type TypeA interface {}
> func main() {
> var a TypeA
> var b *TypeA
> b = &a
> a = b
> a = &a
> b = &a
> }
> Not technically wrong.
the only reason you can do this is because you're using
not just any old interface type, but interface{}, which can
hold any value at all, including a pointer to itself.
it's like a safer version of C's void*.
complaining about the above is like complaining
about the following bit of (correct) C code:
typedef void* TypeA;
void f(){
TypeA a;
TypeA *b;
b = &a;
a = b;
a = &a;
b = &a;
}
it's made safe by the fact that it knows what type is
stored inside it.
in fact in your example you don't even need
to use interface types. you could define TypeA
as
type TypeA *TypeA
and it works ok.
If the value doesn't satisfy the interface, then you can't do it, and
if it does, you can, because there's no problem. That's different from
the pointer case, because X and *X have different behaviours.
> I mean, technically I can do this right?
> package main
> type TypeA interface {}
> func main() {
> var a TypeA
> var b *TypeA
> b = &a
> a = b
> a = &a
> b = &a
> }
> Not technically wrong.
It's not "Not technically wrong". It's just "Not wrong". (Did you mean
to write "b = &a" twice?)
`a` is a variable that can hold any value with at least zero methods,
and all the values you assign to it have that many, so it's OK.
All the values you assign to `b` are pointer-to-TypeA values, so
there's no problem there either.
If you were to try `b = a` you'd get:
cannot use a (type TypeA) as type *TypeA in assignment: need type assertion
so the language is preventing things that I think you think need
preventing.
> Just syntactically, odd.
There's nothing /syntactically/ odd about it at all. And the type
system is quite straightforward.
--
Chris "allusive" Dollin
Yeah, it's syntactic sugar.
They could have made you do the conversion explicitly, eg.
type TypeA interface{}
func main(){
var a TypeA
b := 1
a = TypeA(b)
}
But interfaces are used so often, all over the place that it starts to
get silly. Since a type is never going to be the interface type
required by a function a conversion would always be needed. This gets
in the way of the idea you're trying to convey.
eg.
io.Copy(io.Writer(buffer),io.Reader(someotherbuffer))
It starts to look really horrible. The compiler knows that buffer has
the methods for an io.Writer and the programmer knows that's what he
wants to do. So it's a lot of clutter for no reason.
So a simple rule, you can assign any type to an interface which
satisfies it's method set.
Everyone remembers it, it's not confusing once you know it and
everything gets a bit clearer.
- jessta
--
=====================
http://jessta.id.au
it doesn't work if TypeA is defined as any pointer type other
than void*. that's because void* is special to the C compiler - it's allowed
to hold any pointer type (except function pointers, but that's
another story).
Go's interfaces are also special - they are allowed to hold any type
at all as long as the type implements the given interface.
since interface{} has no methods any type at all can
be held in it. including *interface{}.
an interface value doesn't *point* to a value; it *holds*
the value.
You can disagree, of course, but as has been nicely pointed out to you
by others, disagreeing with the *syntax* in this case proves you still
misunderstand the semantics of what is happening.
Consider this line:
var err os.Error = X
This code means: X must have a String() string method to be assigned
to this interface. X itself can be of *any* other type (including
pointers) which has a suitable method String() defined on it. Again,
this same statement will work with pointer and with non-pointer types,
as long as the *respective type* implements the method. An interface
is not a pointer to something. It's a container to a value which has
the required methods declared for its type.
> In c, it requires that you have explicitly defined the type as a void * (note the >>> * in the definition)
It doesn't matter.. void* has vastly different semantics, so it's a
poor analogy.
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/blog
http://niemeyer.net/twitter