Go: Embedding a primitive type? - go

Suppose we have this piece of code:
type User struct {
int32
Name string
}
Can this type of embedding be useful?
Does int32 have any methods which other can call on instances of User?
How can I access the value of the int32 that User is embedding?

The type int32 is a predeclared type, it has no methods. To verify:
fmt.Println(reflect.TypeOf(int32(0)).NumMethod()) // Prints 0
You can refer to all embedded fields by using the unqualified type name as the field name (Spec: Struct types), predeclared types are no exception. See this example:
u := User{3, "Bob"}
fmt.Printf("%#v\n", u)
u.int32 = 4
fmt.Println(u.int32)
Output (try it on the Go Playground):
main.User{int32:3, Name:"Bob"}
4
Primary gain of using embedding is:
methods of the embedded type get promoted, so it's easier to implement interfaces (you don't need to provide methods that get promoted)
you can "override" methods of the embedded type (on the embedder type): provide your own implementation which will be called when a value of your embedder type is used
and fields of the embedded type get promoted, so code is shorter to refer to promoted fields (field name is left out).
By embedding predeclared types such as int32, you don't get any advantage over using just a regular field (named, not embedded field), as the int32 type doesn't have any methods or fields.
Going forward, besides not having any advantage, you even have a disadvantage. Since predeclared type names start with lowercased letters, embedding them implicitly makes them unexported, so you can only refer to them in the declaring package of the embedder type. If you make them regular, named fields, you may choose to use an uppercased name to make it exported, or a lowercased name to make it unexported.

Related

Golang reflect get nil pointer underlying type

I would like to know if there is a way to "cast" a nil pointer of a struct into the (empty) struct itself using reflection or anything else.
My method parameters are an empty parent struct as an interface, a field name as a string and the field value as an interface.
The point is to get the real type of the field by going through the parent struct until I find the field matching the given name. I cannot just get the type of the value, because there will be cases where it won't return the correct type (for example a time.Time will be seen as a string).
The method can take any struct as parent, which is why it takes interfaces as parameters.
My problem is that the parent struct that is given is always a empty one (it serves only as a model), with default values. So fields that are pointers to substructs are nil. So to find the field given as parameter, I have to get the underlying substruct instead of the nil pointer to continue the search inside.
I cannot find a way to achieve that, I am not sure if that's even possible.
Any help is welcomed.

What does type ByKey []mr.KeyValue{} mean?

I am completely new in Go and have no idea when different language features bump up together,
type ByKey []mr.KeyValue{}
could any one please explain what this means?
As you can see in golang.org/ref/spec#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.
And in Type_declarations
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.
type ByKey []mr.KeyValue is a type definition. It creates a new type called ByKey with underlying type of []mr.KeyValue. KeyValue is again defined exported type in a different package imported as mr to current file which included type ByKey []mr.KeyValue.

Inheritance syntax. What is the difference?

In Go what is the difference below?
I tried to search, but I couldn't think of a right term to describe them. How are they officially called?
#1 - Parent inside struct:
type MyTime struct {
time.Time
}
#2 - Parent right after my type without struct definition:
type MyTime time.Time
For #2, I can initialize my type with another time.Time like mt := MyTime(t).
How to initialize #1 type with another time.Time variable?
Go is not an object oriented language, there is no type hierarchy and inheritance. For details, see What is the idiomatic way in Go to create a complex hierarchy of structs? and Go embedded struct call child method instead parent method.
Your first example creates a new type MyTime embedding time.Time. By embedding a type, all fields and methods of the embedded type gets promoted and are available as if they were fields or methods of the embedder type, very handy when you want to implement an interface for example (because the promoted methods will "exist" without having to declare them).
You can instantiate it like (for details, see Golang embedded struct type):
t := MyTime{Time: time.Now()}
Your second example creates a new type, all methods will be stripped from it. This comes handy when you do not want the existing methods to be part of the new type. A shining example of this is to define the String() method or override marshaling behavior when you want to call the original behavior in your implementation, for details see Call json.Unmarshal inside UnmarshalJSON function without causing stack overflow. You can create a value of it using a simple type conversion:
t := MyTime(time.Now())

Mimic struct.field using reflect

How can I get the same value as reflect.TypeOf(struct.field) when using FieldByName when the field is an interface type?
As seen here, if a struct field is an interface, reflect.TypeOf(struct.field) gives me the concrete type, but reflect.ValueOf(struct).FieldByName("field").Type() gives me the interface. Is it possible to get the concrete type stored in struct.field using reflect if all I have is struct and "field"?
You should use Elem()
// Elem returns the value that the interface v contains
Correct way to extract the type
reflect.ValueOf(h).Elem().FieldByName("i").Elem().Type().String()

Why use non-struct types in Golang? [duplicate]

I am actually learning golang (from .NET) and there is one thing I don't understand about this language.
Sometimes I find this kind of declaration:
https://github.com/golang/crypto/blob/master/ed25519/ed25519.go
// PublicKey is the type of Ed25519 public keys.
type PublicKey []byte
What does it mean exactly?
Is it a creating a struct which inherit from []byte?
Is it just an alias?
I thought golang forbid inheritance.
It's a type declaration, more specifically a type definition. It creates a new type, having []byte as its underlying type:
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.
New types are created because they can simplify using them multiple times, their identifier (their name) may be expressive in other contexts, and–most importantly–so that you can define (attach) methods to it (you can't attach methods to built-in types, nor to anonymous types or types defined in other packages).
This last part (attaching methods) is important, because even though instead of attaching methods you could just as easily create and use functions that accept the "original" type as parameter, only types with methods can implement interfaces that list ("prescribe") those methods, and as mentioned earlier, you can't attach methods to certain types unless you create a new type derived from them.
As an example, the type []int will never implement the sort.Interface required to be sortable (by the sort package), so a new type sort.IntSlice is created (which is type IntSlice []int) to which the required methods are attached, so you can pass a value of type sort.IntSlice to the sort.Sort() function but not a value of type []int. Since sort.IntSlice has []int as its underlying type, if you have a value of []int, you can simply convert it to sort.IntSlice if you want to sort it, like in this example (try it on the Go Playground):
is := []int{1,3,2}
sort.Sort(sort.IntSlice(is))
fmt.Println(is) // Prints: [1 2 3]
When you create a new type, there is no "inheritance" involved. The new type will have 0 methods. If you want "inheritance-like" functionality, you should check out embedding (in relation with struct types), in which case the embedder type will also "have" the methods of the embedded type.

Resources