Scope visibility of struct members while passing as a argument? - go

While calling json.Decoder.Decode by passing a struct, for instance
type _Sample struct {
first string // this will not be filled because it starts with lower case letter
Second string // it is OK.
}
...
var sample _Sample
err := decoder.Decode(&sample)
According to the Language Specification that writes:
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.
The question is the struct _Sample is not exported, why it is visible by the package json?

Access permission is checked when
You're creating/declaring a variable. The compiler will check the visibility of the name of the type identifier.
Using reflect package to modify a variable.
Calling a constant, global variable, or a function. The visibility of constant/variable/function name will be checked.
Once the variable is created/defined, and when you pass this variable as a function/method argument, the copy (If it is a value, the value is being copied. If it is a pointer, the address is being copied) will be passed to the function/method, and always accessible from the function body through the argument name and type. In encoding/json package, the Decoder.Decode method is defined as,
func (dec *Decoder) Decode(v interface{}) error
thus, anything you passed to the Decoder.Decode method, is always accessible from inside the method body through argument v. Note that the type of v is interface{} not _Sample struct. The visibility is checked when you defined the variable as
var sample _Sample
which was OK since it is done from within the same package. Even an anonymous struct (i.e. no type name identifier is defined for the struct)
aSample := struct {
first string // this will not be filled because it starts with lower case letter
Second string // it is OK.
}{}
//...
err := decoder.Decode(&aSample)
will works. Next, when the decoder fills the struct (through reflection), the visibility of struct members will be checked, and _Sample.first is not visible from inside the json package.

Related

Get operation in a structure in golang [duplicate]

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.

Why can I assign struct functions to members of other structs?

I was just messing around and wrote the below piece of code,
package main
import (
"fmt"
)
type Person struct {
name string
}
func (p Person) printName() {
fmt.Println(p.name)
}
type Man struct {
name string
f func()
}
func main() {
p := Person{name: "John"}
m := Man{name: "Adam"}
m.f = p.printName
p.printName()
m.f()
}
The above code results in the following output. This works across packages too.
John
John
So, here are my questions.
Why does this work?
Struct methods require receivers of the same type. How is the function still able to access members of the Person struct?
What happens when m.f = p.printName is executed in the above example?
This question deals mostly with receivers and may extend a bit to embedding.
From the relevant section of the spec:
A method is a function with a receiver. A method declaration binds an
identifier, the method name, to a method, and associates the method
with the receiver's base type.
MethodDecl = "func" Receiver MethodName Signature [ FunctionBody ] .
Receiver = Parameters .
The receiver is specified via an extra parameter section preceding the
method name. That parameter section must declare a single non-variadic
parameter, the receiver. Its type must be of the form T or *T
(possibly using parentheses) where T is a type name. The type denoted
by T is called the receiver base type; it must not be a pointer or
interface type and it must be defined in the same package as the
method. The method is said to be bound to the base type and the method
name is visible only within selectors for type T or *T.
A non-blank receiver identifier must be unique in the method
signature. If the receiver's value is not referenced inside the body
of the method, its identifier may be omitted in the declaration. The
same applies in general to parameters of functions and methods.
For a base type, the non-blank names of methods bound to it must be
unique. If the base type is a struct type, the non-blank method and
field names must be distinct.
Given type Point, the declarations
func (p *Point) Length() float64 {
return math.Sqrt(p.x * p.x + p.y *p.y)
}
func (p *Point) Scale(factor float64) {
p.x *= factor
p.y *= factor
}
bind the methods Length and Scale, with receiver type *Point, to the
base type Point.
The type of a method is the type of a function with the receiver as
first argument.
For instance, the method Scale has type
func(p *Point, factor float64)
However, a function declared this way is not a method.
Man has a field named f that is a function that takes no arguments and returns nothing.
As we saw above golang internally treats
func (p Person) printName()
as
func printName(p Person)
and this can be considered as a function of no arguments when it acts on a Person struct (and it does because p is a Person and p.printName acts on p). Therefore it is allowed to be assigned to Man.f
So the moment you assigned the f field on the Man struct to a function that has captured the Person instance with name "John" and reads the name from that, therefore you get effect of the second "John" being printed.
The Man.name field has never come into play on that one.
I suspect that what you would expect as normal behaviour can be achieved with struct embedding of Person into a Man.
here is a playground link to demonstrate that
A method, in Go, is basically a function with a receiver. That receiver is wraped by the compiler, and beyond that, there is nothing more different from a normal function. That means, at anywhere, the method always gets the receiver which it is bound to, no matter how you call it, assign it to another variable or anythiing else.
In your code, f is not a method of type Man. It is merely a field of type func(). You can set to anything that match the signature, and the function will know nothing about Man or its instance. That means, m.f has no knowledge of m and no access to m.name or any other field of m.
And a note, you can call methods like: Person.PrintName(p) where p is of type Person.
function in Golang is also a value, it can be passed as parameter or assigned by other function too, method in Golang is also a function, with one different, it has receiver in it's value, so when use assign a method to a function (which have same signature) it's refer to the receiver and executing code in that method to destination function

Can array have methods in Go?

I am learning Go and found this code:
// newTestBlockChain creates a blockchain without validation.
func newTestBlockChain(fake bool) *BlockChain {
db, _ := ethdb.NewMemDatabase()
gspec := &Genesis{
Config: params.TestChainConfig,
Difficulty: big.NewInt(1),
}
gspec.MustCommit(db)
engine := ethash.NewFullFaker()
if !fake {
engine = ethash.NewTester()
}
blockchain, err := NewBlockChain(db, gspec.Config, engine, vm.Config{})
if err != nil {
panic(err)
}
blockchain.SetValidator(bproc{})
return blockchain
}
My question is:
gspec variable is created as an associative array of 2 values with key 'Config' and key 'Difficulty', that's clear.
But then I see this line:
gspec.MustCommit(db)
and I don't understand, where was the 'MustCommit()' function declared? Also, does an array in Go have methods? Weird stuff. Only class can have methods in my understanding of software development and here, I am seeing an array that has functions (methods). What is up with this code?
gspec variable is created as an associative array of 2 values with key
'Config' and key 'Difficulty' , that's clear.
It is not clear. It is false. Genesis is a struct. gspec is a pointer to a struct. A struct is not an associative array. In Go, a map is an associative array.
You have:
gspec := &Genesis{
Config: params.TestChainConfig,
Difficulty: big.NewInt(1),
}
Where
// Genesis specifies the header fields, state of a genesis block. It also defines hard
// fork switch-over blocks through the chain configuration.
type Genesis struct {
Config *params.ChainConfig `json:"config"`
Nonce uint64 `json:"nonce"`
Timestamp uint64 `json:"timestamp"`
ExtraData []byte `json:"extraData"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc GenesisAlloc `json:"alloc" gencodec:"required"`
// These fields are used for consensus tests. Please don't use them
// in actual genesis blocks.
Number uint64 `json:"number"`
GasUsed uint64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
}
https://godoc.org/github.com/ethereum/go-ethereum/core#Genesis
Composite literals
Composite literals construct values for structs, arrays, slices, and
maps and create a new value each time they are evaluated. They consist
of the type of the literal followed by a brace-bound list of elements.
Each element may optionally be preceded by a corresponding key.
Taking the address of a composite literal generates a pointer to a
unique variable initialized with the literal's value.
gspec := &Genesis{
Config: params.TestChainConfig,
Difficulty: big.NewInt(1),
}
gspec is constructed using a Go composite literal.
Method declarations
A method is a function with a receiver. A method declaration binds an
identifier, the method name, to a method, and associates the method
with the receiver's base type.
The receiver is specified via an extra parameter section preceding the
method name. That parameter section must declare a single non-variadic
parameter, the receiver. Its type must be of the form T or *T
(possibly using parentheses) where T is a type name. The type denoted
by T is called the receiver base type; it must not be a pointer or
interface type and it must be defined in the same package as the
method.
A type of the form T or *T (possibly using parentheses), where T is a type name. may have methods; it must not be a pointer or interface type. A Go array type may have methods. A Go map (associative array) type may have methods. A Go struct type may have methods.
Go does not have classes.
References:
The Go Programming Language Specification
Your assumption is wrong. gspec isn't an associative array, but a object of type Genesis. The Genesis type is probably some sort of struct-type with various attributes and methods.
For examples on structs and methods you could visit the following Go by Example pages:
Structs
Methods

Golang not able to detect implicitly typed const when assigning to a variable

When I try to assign an implicitly typed constant to a variable, the assigned variable doesn't detect the custom type and instead gets assigned as the underlying primitive type. i.e;
For:
type Custom string
const (
First Custom = "10"
Second = "20"
)
If I have a function:
func SomeFunc( x Custom) {
fmt.Printf("Inside func %v %v", x, reflect.TypeOf(x))
}
Then when I:
out := Second
SomeFunc(out)
it errors with:
cannot use out (type string) as type Custom in argument to SomeFunc
However SomeFunc(Second) works fine.
Also
fmt.Printf("%v %v\n",reflect.TypeOf(second),reflect.TypeOf(out)) //prints string string
Here is the reproducer: https://play.golang.org/p/Iv-C1ee992
Can someone help me understand what is happening here?
Second is an untyped const and has this property (https://blog.golang.org/constants):
An untyped constant is just a value, one not yet given a defined type
that would force it to obey the strict rules that prevent combining
differently typed values.
...
Assigning them to a variable of any type compatible with strings works
without error.
On the contrary out is a variable of type string. Again from the blog post:
and by now you might be asking, "if the constant is untyped, how does
str get a type in this variable declaration?" The answer is that an
untyped constant has a default type, an implicit type that it
transfers to a value if a type is needed where none is provided. For
untyped string constants, that default type is obviously string

Call struct literal's method

This code works fine:
feedService := postgres.FeedService{}
feeds, err := feedService.GetAllRssFeeds()
But this code gives me error:
feeds, err = postgres.FeedService{}.GetAllRssFeeds()
controllers\feed_controller.go:35: cannot call pointer method on
postgres.FeedService literal controllers\feed_controller.go:35: cannot
take the address of postgres.FeedService literal
Why this two pieces of code is not equal ?
Here is a struct declaration:
type FeedService struct {
}
func (s *FeedService) GetAllRssFeeds() ([]*quzx.RssFeed, error) {
Your FeedService.GetAllRssFeeds() method has pointer receiver, so a pointer to FeedService is needed to call this method.
In your first example you use a short variable declaration to store a FeedService struct value in a local variable. Local variables are addressable, so when you write feedService.GetAllRssFeeds() after that, the compiler will automatically take the address of feedService and use that as the receiver value. It is a shorthand for:
feeds, err := (&feedService).GetAllRssFeeds()
It is in Spec: Calls:
If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
In your second example you don't create a local variable, you just use a struct composite literal, but by itself it is not (automatically) addressable, so the compiler cannot obtain a pointer to FeedService value to be used as the receiver, and hence cannot call the method.
Note that it is allowed to take the address of a composite literal explicitly, so the following also works:
feeds, err := (&postgres.FeedService{}).GetAllRssFeeds()
This is in Spec: Composite literals:
Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.
See related questions:
What is the method set of `sync.WaitGroup`?
Calling a method with a pointer receiver by an object instead of a pointer to it?

Resources