In Golang, I can have an embedded fields inside of a struct. The embedded field gets "promoted", and the new struct gets to use all the functions of the embedded fields as if it's part of itself. So my question is, does the embedded fields' functions count towards interface implementation? For example:
type Foo struct {
Name string
}
func (f *Foo) Name() {
fmt.Println(f.Name)
}
type Hello interface {
Name()
Hello()
}
type Bar struct {
World string
*Foo
}
func (b *Bar) Hello() {
fmt.Println("Hello")
}
In the code above, Bar{} does not implement a function named Name(), but Foo{} does. Since Foo{} is an embedded field inside of Bar{}, is Bar{} a Hello type?
Here's how to trace this down in the language specification
Find out what it means to implement an interface in the "Interface types" section:
Interface types ¶
An interface type specifies a method set called its interface. A
variable of interface type can store a value of any type with a method
set that is any superset of the interface. Such a type is said to
implement the interface.
Or from the section on "Method sets"
The method set of a type determines the interfaces that the type implements...
So what is important is the method set of the type you want to implement the interface. Let's see what constitutes a method set in the case of embedded fields:
The first place I checked was the section "Method Sets", but it sends us elsewhere:
Further rules apply to structs containing embedded fields, as described in the section on struct types.
So we go to the section "Struct types" and find:
A field or method f of an embedded field in a struct x is called
promoted if x.f is a legal selector that denotes that field or method
f.
...
Given a struct type S and a defined type T, promoted methods are
included in the method set of the struct as follows:
If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
So, given that the methods of the embedded field are promoted, they are included in the method set of the containing struct. As we saw above the method set of any type is what determines whether it implements an interface.
Related
This question already has answers here:
Embedding instead of inheritance in Go
(7 answers)
Closed last year.
Below is a simple program. But what I don't understand is that how is the Get operation working? I have not defined any Get Method, but form.Get is working. How?
Sincerely,
Sudarsan.D
package main
import (
"fmt"
"net/url"
)
type errors map[string]string;
type Form struct {
url.Values;
Errors errors;
}
func New (data url.Values) (*Form) {
return &Form {
data,
errors(map[string]string{}),
};
}
func main () {
k1 := url.Values{};
k1.Set("arvind","superstar");
k1.Set("title","Arvind");
form := New(k1);
fmt.Println("The title is", form.Get("arvind"));
}
Because in the Form struct you did not provide a name explicitly for the url.Values field, that field is said to be embedded. An embedded field's name is automatically set to the type's unqualified name, i.e. in this case the url.Values field's name becomes Values. Also, an embedded field type's methods (if it has any) and fields (if it is a struct with any) are said to be promoted to the embedding struct. A promoted method or field can be accessed directly through the embedding struct, without having to specify the embedded field's name. i.e. instead of form.Values.Get("arvind") you can do form.Get("arving").
Keep in mind that the two expressions form.Values.Get("arvind") and form.Get("arving") are semantically equivalent. In both cases you are calling the method Get on the form.Values field even though in the second expression the field's name is omitted.
From the language spec on Struct types:
A struct is a sequence of named elements, called fields, each of which
has a name and a type. Field names may be specified explicitly
(IdentifierList) or implicitly (EmbeddedField).
...
A field declared with a type but no explicit field name is called an
embedded field. An embedded field must be specified as a type name T
or as a pointer to a non-interface type name *T, and T itself may not
be a pointer type. The unqualified type name acts as the field name.
...
A field or method f of an embedded field in a struct x is called
promoted if x.f is a legal selector that denotes that field or method
f.
...
Given a struct type S and a defined type T, promoted methods are
included in the method set of the struct as follows:
If S contains an embedded field T, the method sets of S and *S both
include promoted methods with receiver T. The method set of *S also
includes promoted methods with receiver *T.
If S contains an embedded
field *T, the method sets of S and *S both include promoted methods
with receiver T or *T.
I'm not able to understand how the String() method works for embedded structs in Go. Consider this:
type Engineer struct {
Person
TaxPayer
Specialization string
}
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("name: %s, age: %d", p.Name, p.Age)
}
type TaxPayer struct {
TaxBracket int
}
func (t TaxPayer) String() string {
return fmt.Sprintf("%d", t.TaxBracket)
}
func main() {
engineer := Engineer{
Person: Person{
Name: "John Doe",
Age: 35,
},
TaxPayer: TaxPayer{3},
Specialization: "Construction",
}
fmt.Println(engineer)
}
The output of this code is {name: John Doe, age: 35 3 Construction}. But if I remove the Person.String() method definition then the output is just 3 (it calls engineer.TaxPayer.String()). However if I remove TaxPayer.String() method definition as well, then the output is {{John Doe 35} {3} Construction}. I initially thought there must be an implicit String() method defined for the overall Engineer struct, but there is no such method.
Why is method invocation behaving this way? If I instead have the methods for each embedded type named anything other than String() (say Foo()), and then try to do fmt.Println(engineer.Foo()), I get an (expected) compilation error: ambiguous selector engineer.Foo. Why is this error not raised when the methods' name is String() instead?
If you embed types in a struct, the fields and methods of the embedded type get promoted to the embedder type. They "act" as if they were defined on the embedder type.
What does this mean? If type A embeds type B, and type B has a method String(), you can call String() on type A (the receiver will still be B, this is not inheritance nor virtual method).
So far so good. But what if type A embeds type B and type C, both having a String() method? Then A.String() would be ambiguous, therefore in this case the String() method won't be promoted.
This explains what you experience. Printing Engineer will have the default formatting (struct fields) because there would be 2 String() methods, so none is used for Engineer itself. Of course the default formatting involves printing the fields, and to produce the default string representation of a value, the fmt package checks if the value being printed implements fmt.Stringer, and if so, its String() method is called.
If you remove Person.String(), then there is only a single String() method promoted, from TaxPlayer, so that is called by the fmt package to produce the string representation of the Engineer value itself.
Same goes if you remove TaxPayer.String() : then Person.String() will be the only String() method promoted, so that is used for an Engineer value itself.
This is detailed in Spec: Struct types:
A field or method f of an embedded field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.
[...] Given a struct type S and a defined type T, promoted methods are included in the method set of the struct as follows:
If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
The first sentence states "if x.f is a legal selector". What does legal mean?
Spec: Selectors:
For a primary expression x that is not a package name, the selector expression
x.f
denotes the field or method f of the value x.
[...] A selector f may denote a field or method f of a type T, or it may refer to a field or method f of a nested embedded field of T. The number of embedded fields traversed to reach f is called its depth in T. The depth of a field or method f declared in T is zero. The depth of a field or method f declared in an embedded field A in T is the depth of f in A plus one.
The following rules apply to selectors:
For a value x of type T or *T where T is not a pointer or interface type, x.f denotes the field or method at the shallowest depth in T where there is such an f. If there is not exactly one f with shallowest depth, the selector expression is illegal.
[...]
The essence is emphasized, and it explains why none of the String() methods are called in the first place: Engineer.String() could come from 2 "sources": Person.String and TaxPayer.String, therefore Engineer.String is an illegal selector and thus none of the String() methods will be part of the method set of Engineer.
Using an illegal selector raises a compile time error (such as "ambiguous selector engineer.Foo"). So you get the error because you explicitly tried to refer to engineer.Foo. But just embedding 2 types both having String(), it's not a compile-time error. The embedding itself is not an error. The use of an illegal selector would be the error. If you'd write engineer.String(), that would again raise a compile time error. But if you just pass engineer for printing: fmt.Println(engineer), there is no illegal selector here, you don't refer to engineer.String(). It's allowed. (Of course since method set of Engineer does not have a promoted String() method, it won't be called to produce string representation for an Engineer–only when printing the fields.)
type A interface {
f()
}
type B struct {
A
}
type C struct {
Imp A
}
func main() {
b := B{}
c := C{}
//b can be directly assigned to the A interface, but c prompts that it cannot be assigned
var ab A = b
//Cannot use 'c' (type C) as type A in assignment Type does not implement 'A' as some methods are missing: f()
var ac A = c
}
what's the different between in the B struct and C struct?
in Go sheet
A field declared with a type but no explicit field name is called an embedded field. An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.
If you continue reading the same section of the spec of the spec, you will notice the following:
Given a struct type S and a defined type T, promoted methods are
included in the method set of the struct as follows:
If S contains an embedded field T, the method sets of S and *S both
include promoted methods with receiver T. The method set of *S also
includes promoted methods with receiver *T.
If S contains an embedded
field *T, the method sets of S and *S both include promoted methods
with receiver T or *T.
Your struct B has no methods explicitly defined on it, but B's method set implicitly includes the promoted methods from the embedded field. In this case, the embedded field is an interface with method f(). You can use any object that satisfies that interface and its f() method will automatically be part of the method set for B.
On the other hand, your C struct has a named field. The methods on Imp do not get automatically added to C's method set. Instead, to access the f() method from Imp, you would need to specifically call C.Imp.f().
Finally: the fact that you're using an interface as the (embedded or not) field does not matter, it could easily be another struct that has a f() method. The important part is whether f() becomes part of the parent struct's method set or not, which will allow it to implement A or not.
This is a Go grammar question and seems a stupid question but I've been checking the Go language specification to find some official words or definitions to define what type is a xxx type, say, what type is an interface type?
For example, I see words like these:
The method set of an interface type is its interface.
Or
An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type.
Or
Consider a struct type T with two methods ...
type T struct {
a int
}
....
A type literal like struct {...} is a struct type, what about A in
type A struct {...} and B in type B interface{...}? Is A a struct type and B an interface type?
Yes, from the above sample for the struct type T, I can tell that a defined type (by the "type" declaration) whose given type is a struct type or interface type is also a struct or interface type. So A is a struct type and B is an interface type also. But where are the official definitions of this rule?
For defined types I can only find the following relating to type categories:
A type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it.
So my understanding is that the defined type is a new, distinct type with the given type, but they are in the same type category, say, interface types or struct types. Still, there are no such definitions.
TLDR;
The kind of type T is interface if its underlying type is an interface type.
The kind of type T is struct if its underlying type is a struct type.
Spec: Struct types and Spec: Interface types specifies exactly what are the struct and interface types:
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
EmbeddedField = [ "*" ] TypeName .
Tag = string_lit .
InterfaceType = "interface" "{" { MethodSpec ";" } "}" .
MethodSpec = MethodName Signature | InterfaceTypeName .
MethodName = identifier .
InterfaceTypeName = TypeName .
So for example these are struct types:
struct { A int }
struct {}
struct { _ int }
and these are interface types:
interface { String() string }
interface {}
We may use a type declaration to create a new type, such as:
type Point struct { X, Y int }
The above type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it. The definition of underlying type is recursive:
Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself. Otherwise, T's underlying type is the underlying type of the type to which T refers in its type declaration.
When we talk about arbitrary types being structs or interfaces, we're talking about their kind.
In the light of this, basically your question is equivalent to this:
"When is the kind of an arbitrary type interface or struct?"
The answer to this question is not in the spec, but this is how we could define it:
The kind of a type T is interface if its underlying type is an interface type.
Similarly:
The kind of a type T is struct if its underlying type is a struct type.
So for example:
type Point struct { X, Y int }
type PP Point
Is the type struct { X, Y int } of kind struct? Yes, because since it's a type literal, its underlying type is itself, and it's by definition a struct type.
Is Point a struct? Since the underlying type of Point is the underlying type of the type to which it refers in its type declaration, which is a type literal (see above), it is of struct type (its kind is struct).
Is PP a struct? Since its underlying type is the underlying type of the type to which it refers in its type declaration (which is Point), whose underlying type is a struct type literal, yes, it is also a struct type.
This kind we're talking about is represented by the reflect.Kind type. There are reflect.Interface and reflect.Struct constants (of type reflect.Kind) to represent the struct and interface kinds. And the reflect.Type type descriptor has a Type.Kind() method to access this kind.
This is how you can check if the type (kind) of some value is a struct for example:
func isStruct(i interface{}) bool {
return reflect.TypeOf(i).Kind() == reflect.Struct
}
Testing it (try it on the Go Playground):
fmt.Println(isStruct(Point{})) // true
fmt.Println(isStruct(PP{})) // true
fmt.Println(isStruct(struct{}{})) // true
fmt.Println(isStruct("text")) // false
Checking for interface type is a little more complicated because passing an interface value to a function that expects interface{} will not pass the interface value as-is but the concrete value "stored" in it, and as an interface{} value. We would have to pass a pointer to interface (which otherwise rarely makes sense in Go), access the element type and check its kind. For details, see this answer: What is the difference between reflect.ValueOf() and Value.Elem() in go?
An interface type is a type introduced by the interface keyword, or a name for such a type as defined by type name interface (plus of course the actual requirements for that interface).
Any type, whether it is an interface type or not, implements an interface type if it has the appropriate set of named methods. That is, a struct type may be sufficient to be used with some interface type. Even a non-struct type may be sufficient:
type foo int
func (receiver_arg foo) method1() { ... }
Type-name foo now implements any interface that requires a method named method1 (provided of course that it implements the rest of any required methods).
... the defined type [via the type keyword] is a new, distinct type with the given type, but they are in the same type category ...
Yes, just so. Using reflect, you'll find that they have the same Kind. The word kind isn't in the spec like this but it's quite useful, and the link here enumerates all the fundamental type-kinds in Go.
The address of a composite literal is evaluated as the literal itself when used as an interface. Can somebody please point to the part of the ref spec which deals with this ?
package main
import "fmt"
type ntfc interface {
rx() int
}
type cncrt struct {
x int
}
func (c cncrt) rx() int{
return c.x
}
func rtrnsNtfca() ntfc {
return &cncrt{3}
}
func rtrnsNtfc() ntfc {
return cncrt{3}
}
func rtrnsCncrt() *cncrt {
return &cncrt{3}
}
func main() {
fmt.Println(rtrnsNtfca().rx())
fmt.Println(rtrnsNtfc().rx())
fmt.Println(rtrnsCncrt().rx())
}
Also here. For future ref., is it acceptable to just link to the playground without including the code here?
Spec: Method sets:
A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).
So the method set of *cncrt includes the methods set of cncrt. Since rx() is an element of cncrt's method set, it will also be in *cncrt's method set. Which means both cncrt and *cncrt types implement the ntfc interface.
If you have a pointer value (*cncrt) and you call rx() on it, the pointer will automatically be dereferenced which will be the receiver of the rx() method.
In your rtnsNtfca() and rtnsNtfc() functions an interface value of ntfc will automatically be created and returned. Interface values in Go are represented as (type;value) pairs (for more details: The Laws of Reflection #The representation of an interface). So both rtnsNtfca() and rtnsNtfc() return an interface value, but the first one holds a dynamic value of type *cncrt and the latter one holds a dynamic value of type cncrt.
And your 3rd method rtrnsCncrt() returns a concrete type (*cncrt), there is no interface wrapping involved there.
Note: "The other way around"
Spec: Calls:
If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
This means if you would have declared rx() to have a pointer receiver, and you have a variable of type cncrt (note: not pointer), you could still call the rx() method on it if it is addressable, and the address would be taken automatically and used as the receiver.