Just curious, is there a way to export a function whose name starts with a lower case character, like "print" or "start"?
A side note: just like you do with JSON:
type T struct {
FieldA int `json:"field_a"`
FieldB string `json:"field_b,omitempty"`
}
No, there is not. The Go language specification specifies this clearly:
Exported identifiers
An identifier may be exported to permit access to it from another package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
the identifier is declared in the package block or it is a field name or method name.
All other identifiers are not exported.
Related
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.
Suppose I have the following code:
type User struct {
ID string
Username string
Name string
Password string
}
What I want to do is create another struct that can access certain fields from the User struct, instead of accessing all of it, to prevent people from seeing the password, for example.
This does not work:
type Note struct {
ID string
Text string
UserID User.ID
}
Is there any way to do this, or do I simply create the Note.UserID field to have the same data type as the ID in the User struct?
Assuming the types are in different packages you can do this by exporting vs not exporting the fields. A field who's name begins with a lower case letter is not exported, meaning it is not visible outside the package where it is declared/defined. So, in this case if the user existed in one package, call it user while the other type were declared in another you could accomplish this 'hiding' of properties by changing the definition to;
type User struct {
ID string
username string
name string
password string
}
If the two types live in the same package there is no way of making a field private/hidden/ect, everything will be available in that scope.
The Go Programming Language Specification
Exported identifiers
An identifier may be exported to permit access to it from another
package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case
letter (Unicode class "Lu"); and
the identifier is declared in the package block or it is a field name
or method name.
All other identifiers are not exported.
Give User its own package and don't export the password.
For example,
package user
type User struct {
ID string
Username string
Name string
password string
}
func (u *User) IsPassword(password string) bool {
return password == u.password
}
Why can I do this
package main
import "fmt"
func main() {
c := Circle{x: 0, y: 0, r: 5}
fmt.Println(c.r)
}
type Circle struct {
x float64
y float64
r float64
}
http://play.golang.org/p/0ypcekVDV9
When I can't do the same with a struct in a package?
If I would try to access a struct with a field with lowercase a compiler error is returned..
As already stated, the fields need to be exported to be accessible from another package. See the spec
Exported identifiers
An identifier may be exported to permit access to it from another
package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case
letter (Unicode class "Lu");
and the identifier is declared in the
package block or it is a field name or method name. All other
identifiers are not exported.
If you want to keep the fields private, you need to use accessor (set/get) methods which you can read about here
Getters
Go doesn't provide automatic support for getters and setters. There's
nothing wrong with providing getters and setters yourself, and it's
often appropriate to do so, but it's neither idiomatic nor necessary
to put Get into the getter's name. If you have a field called owner
(lower case, unexported), the getter method should be called Owner
(upper case, exported), not GetOwner. The use of upper-case names for
export provides the hook to discriminate the field from the method. A
setter function, if needed, will likely be called SetOwner. Both names
read well in practice:
owner := obj.Owner()
if owner != user {
obj.SetOwner(user)
}
If the struct is in a different package than the main function, then you cannot access the struct's private fields from that main function.
That is what "private" means.
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.
type Config struct {
CommitIndex uint64 `json:"commitIndex"`
// TODO decide what we need to store in peer struct
Peers []*Peer `json:"peers"`
}
I understand what the first two columns are,but what is json:"commitIndex"?
It's called a struct tag, they can be parsed using the reflect package at runtime.
From https://golang.org/ref/spec#Struct_types:
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 and take part in type identity for structs but are otherwise ignored.
Some packages that use reflection like json and xml use tags to handle special cases better.
What you are referring to is called a tag, and the Go specification states:
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 and take part in type identity for structs 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"
}
This does nothing at compile time, but is used by different packages when doing runtime reflection on the struct. As Amit already pointed out, the encoding/json package is using it to specify marshalling/unmarshalling behaviour. The same goes with encoding/xml, gopkg.in/mgo.v2/bson, etc.
The tag string is by convention a space separated string. As stated in the reflect package:
By convention, tag strings are a concatenation of optionally
space-separated key:"value" pairs. Each key is a non-empty string
consisting of non-control characters other than space (U+0020 ' '),
quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted using
U+0022 '"' characters and Go string literal syntax.