I came across this type declaration:
type Handler func(*Conn)
type Server struct {
Handshake func(*Config, *http.Request) error
Handler
}
(this is a simplified version of https://github.com/golang/net/blob/38c17adf51120973d1735785a7c02f8ce8297c5e/websocket/server.go#L55-L66
The second field in the Server structure is anonymous. There is just type and no name.
Here is the grammar for type declarations (https://golang.org/ref/spec#Type_declarations):
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = identifier Type .
and it clearly requires an identifier name. But yet the section that I referenced that contains the grammar, also mentions anonymous fields.
I do not understand why this syntax is correct and how anonymous fields are used.
You want to look at the part of the grammar that has to do with structures, not just types. See: Struct types and the use of AnonymousField. Looking just at the production for TypeSpec is focusing attention on the wrong place. Instead, look at FieldDecl; the grammar shows that we have two possibilities: named fields (IdentifierList Type), or anonymous fields (AnonymousField).
Anonymous fields are typically used for embedding. In your example, a Server will act like a Handler because it has embedded that field.
Related
Why we don't call person field as embedded?
“type user struct {
name string
email string
}
type admin struct {
person user // NOT Embedding
level string
}”
But in other cases like below we call it embedded:
“type user struct {
name string
email string
}
type admin struct {
user // Value Semantic Embedding
level string
}”
What I think is that person is also embedded like value/pointer semantic embedding. What I'm missing here?
Because that's how the Go language specification defines it:
A field declared with a type but no explicit field name is called an embedded field.
I can see how the term "embedded" would be confusing. After all, named and unnamed fields end up with the same memory layout, "embedded" into the parent struct. "Anonymous field" might have been a better name for it, but that's not the name that the Go language designers chose.
With the first code you can't treat an admin object as a user object, like using member access or type assertion. This also affects how an embedding struct satisfies interfaces.
For example, the following code works with proper embedding, but not a simple member struct:
var a admin
a.name = "asdfg"
u := a.(user)
I wonder is there any solution for this.
TYPES: BEGIN OF ty_table1,
field1 TYPE string,
END OF ty_table1,
tt_table1 type STANDARD TABLE OF ty_table1 with EMPTY KEY,
BEGIN OF ty_table2,
field1 TYPE string,
END OF ty_table2,
tt_table2 type STANDARD TABLE OF ty_table2 with EMPTY KEY.
DATA: lt_table TYPE table OF ty_table1,
lt_final TYPE table OF ty_table2.
DATA(lt_table1) = VALUE tt_table1( FOR <fs_struct> IN lt_table WHERE ( field1 EQ 'TEST' )
( CORRESPONDING #( <fs_struct> ) ) ).
DATA(lt_table2) = VALUE tt_table2( FOR <fs_struct> IN lt_final WHERE ( field1 EQ 'TEST1' )
( CORRESPONDING #( <fs_struct> ) ) ).
Here, we will be getting a syntax error in the 2nd constructor expression stating:
"<FS_STRUCT>" was already declared with the type "TY_TABLE1" and cannot be used with the type "TY_TABLE2" here.
Is there any way to "unassign" <FS_STRUCT> after the 1st statement? So that, it can be used in the next forthcoming FOR statements for different tables.
The normal UNASSIGN statement can't be used to unassign <fs_struct> since it won't have scope outside the FOR loop.
The target field of a FOR statement has the same semantics as LET expressions:
A helper field specified in a LET expression is valid in the context in which the LET expression is specified. This can be a full expression or just part of an expression. All helper fields of a full expression are in the same namespace. A previously specified helper field cannot be specified in a further LET expression of the same expression. Furthermore, the helper fields are in the same namespace as the data objects or field symbols of the current procedure or program. Helper fields cannot be defined in a LET expression if a data object or field symbol with the same name already exists in the procedure or program of the expression. Conversely, no data objects or field symbols with names assigned to helper fields can be declared after an expression with a LET expression.
When reusing helper fields in different expressions, the following applies:
If a helper field is defined for the first time in the current procedure or program, it is declared inline.
If a helper field in the current procedure or program is defined again in a LET expression of a different expression and the derived data type matches, the helper field is bound to this expression and can be used there.
If a helper field in the current procedure or program is defined again in a LET expression of a different expression and the derived data type does not match, the helper field cannot be used there and a syntax error occurs.
Thus in fact there are two different declarations in your code (which in theory could hold different types). However the ABAP language enforces that the types match, probably to avoid confusing situations where variables with the same name suddenly hold different types (also this might be needed to prevent collisions at runtime).
There is also no way to influence the type inferred for a a local variable declared with LET².
From that I'd say the answer is clearly no, and you really should use different names for different types. Also using CORRESPONDING on a generic field symbol sounds quite dangerous to me, I'd avoid that.
²Except you change the value from which the type is derived, eg. by CONVerting one table to the other (though that probably won't work for your case):
DATA(second_result) = VALUE second_table_type(
FOR <entry> IN CONV first_table_type( second_source )
WHERE ( field1 EQ 'TEST1' )
( CORRESPONDING #( <entry> ) )
).
I was reading this slideshow, which says:
var hits struct {
sync.Mutex
n int
}
hits.Lock()
hits.n++
hits.Unlock()
How does that work exactly? Seems like hits isn't composed of a mutex and integer, but is a mutex and integer?
It is composition. Using an anonymous field (embedded field), the containing struct will have a value of the embedded type, and you can refer to it: the unqualified type name acts as the field name.
So you could just as easily write:
hits.Mutex.Lock()
hits.n++
hits.Mutex.Unlock()
When you embed a type, fields and methods of the embedded type get promoted, so you can refer to them without specifying the field name (which is the embedded type name), but this is just syntactic sugar. Quoting from Spec: Selectors:
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.
Beyond the field / method promotion, the method set of the embedder type will also contain the method set of the embedded type. Quoting from Spec: Struct types:
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.
This is not inheritance in the OOP sense, but something similar. This comes handy when you want to implement an interface: if you embed a type that already implements the interface, so will your struct type. You can also provide your own implementation of some methods, which gives the feeling of method overriding, but must not be forgetten that selectors that denote methods of the embedded type will get the embedded value as the receiver (and not the embedder value), and selectors that denote your methods defined on the struct type (that may or may not "shadow" a method of the embedded type) will get the embedder struct value as the receiver.
It's called embedding, hits is composed of a sync.Mutex and an int. This should be true since there is really no inheritance in Go. This is more of a "has a" rather than an "is a" relationship between the members and the struct.
Read here for a more complete explanation
Quoted from the link
The methods of embedded types come along for free
That means you can access them like hits.Lock() instead of the longer form hits.Mutex.Lock() because the function Lock() is not ambiguous.
See the Go-syntax representation of hits variable:
fmt.Printf("%#v\n", &hits)
// &struct { sync.Mutex; n int }{Mutex:sync.Mutex{state:0, sema:0x0}, n:1}
When you declare the variable, it simply initializes the fields in struct with their default values.
Also, compiler automatically sets the name of the embedded struct as a field. So you can also access like:
hits.Mutex.Lock()
hits.Mutex.Unlock()
And you have access to all methods and exported fields (if any) of sync.Mutex.
In Golang spec:
type (
T0 []string
T1 []string
)
it says T0 and T1 are different because they are named types with distinct declarations.but there is a rule:
Two named types are identical if their type names originate in the same TypeSpec.
so why T0 and T1 are different?
EDIT:
in spec it also says:
A type declaration binds an identifier, the type name, to a new type
that has the same underlying type as an existing type, and operations
defined for the existing type are also defined for the new type. The
new type is different from the existing type.
Given:
type (
T0 []string
T1 []string
)
The Go Programming Language Specification
Version of June 28, 2017
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.
TypeDef = identifier Type .
The new type is called a defined type. It is different from any other
type, including the type it is created from.
A defined type is always different from any other type. Otherwise, two
types are identical if their underlying type literals are structurally
equivalent; that is, they have the same literal structure and
corresponding components have identical types.
T0 and T1 are defined types and are, therefore, different.
References:
The Go Programming Language
Specification
Version of June 28, 2017
Types
A type determines a set of values together with operations and methods
specific to those values. A type may be denoted by a type name, if it
has one, or specified using a type literal, which composes a type from
existing types.
Named instances of the boolean, numeric, and string types are
predeclared. Other named types are introduced with type declarations.
Type declarations
A type declaration binds an identifier, the type name, to a type. Type
declarations come in two forms: alias declarations and type
definitions.
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = AliasDecl | TypeDef .
Alias declarations
An alias declaration binds an identifier to the given type.
AliasDecl = identifier "=" Type .
Within the scope of the identifier, it serves as an alias for the
type.
Type definitions
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.
TypeDef = identifier Type .
The new type is called a defined type. It is different from any other
type, including the type it is created from.
Type identity
Two types are either identical or different.
A defined type is always different from any other type. Otherwise, two
types are identical if their underlying type literals are structurally
equivalent; that is, they have the same literal structure and
corresponding components have identical types.
I've been trying to find out how to use mgo (MongoDB driver for Go) and I came across this struct declaration:
type Something struct {
Id bson.ObjectId "_id,omitempty"
Name string
}
I don't quite understand the syntax of the first element (Id). I understand that it's being declared as type bson.ObjectId, but what is the string literal doing there?
My question is not about the mgo driver functionality,
but about this strange <name> <type> <string_literal> syntax.
I couldn't find anything on the Go specs, and I don't know how to google this either.
It's explained in the Struct types section of the language specification:
A field declaration may be followed by an optional string literal
tag, which becomes an attribute for all the fields in the corresponding field declaration. The tags are made visible through a
reflection interface but are otherwise ignored.
// A struct corresponding to the TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers.
struct {
microsec uint64 "field 1"
serverIP6 uint64 "field 2"
process string "field 3"
}