Embedded struct - go

Is it possible to inherit methods of a type without using embedded structs?
The first snippet of code is working code that embeds the Property struct in Node and I'm able to call node.GetString that's a method on Properties. The thing I don't like about this is when I initialize Node I have(?) to initialize the Properties struct within it. Is there a way around this?
package main
import "fmt"
type Properties map[string]interface{}
func (p Properties) GetString(key string) string {
return p[key].(string)
}
type Nodes map[string]*Node
type Node struct {
*Properties
}
func main() {
allNodes := Nodes{"1": &Node{&Properties{"test": "foo"}}} // :'(
singleNode := allNodes["1"]
fmt.Println(singleNode.GetString("test"))
}
Ultimately, I would like to do something like the following. Where Node is of type Properties and initializing does not require initializing a Property struct too. The following code doesn't work but may be clear what my goal is.
package main
import "fmt"
type Properties map[string]interface{}
func (p Properties) GetString(key string) string {
return p[key].(string)
}
type Nodes map[string]*Node
type Node Properties
func main() {
allNodes := Nodes{"1": &Node{"test": "foo"}} // :)
singleNode := allNodes["1"]
fmt.Println(singleNode.GetString("test")) // :D
}
I'll be adding more structs that will use Properties's methods which is why I'm asking. If I only had Node, I would just have methods for Node and be done. But because I'll have more than Node I find it kind of redundant to add the same methods to all the structs that embed Properties
I guess more to the exact problem, I want to use Properties methods from Node without having to initialize Properties.

So you're running into an idiosyncrasy of Go here. Embedding is the only way in which methods of one struct can get "promoted" to appear to exist on another struct. While it feels intuitive that type Node Properties should expose the Properties methods on Node, that effect of that syntax is for Node to take on the memory layout of Properties but not any of its methods.
It doesn't explain why this design choice was made but the Go Spec is at least specific if dry. If you read it exactly as it appears, with no interpretation, it is very accurate:
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
GetString has a receiver of type Properties not Node, seriously, interpret the spec like you're an accountant with no imagination. With that said:
Further rules apply to structs containing anonymous fields, as described in the section on struct types.
...
A field or method f of an anonymous field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.
Promoted fields act like ordinary fields of a struct except that they
cannot be used as field names in composite literals of the struct.
Given a struct type S and a type named T, promoted methods are
included in the method set of the struct as follows:
If S contains an anonymous 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 anonymous
field *T, the method sets of S and *S both include promoted methods
with receiver T or *T.
That line about composite literals is this thing that forces you to declare Properties inside every Node you create.
p.s. Hi Jeff!

The short answer to your last question is simply No.
There is a big difference between type declaration and embedding in golang, you can make your last example working by manually make a type conversion between Node and Properties:
package main
import "fmt"
type Properties map[string]interface{}
func (p Properties) GetString(key string) string {
return p[key].(string)
}
type Nodes map[string]*Node
type Node Properties
func main() {
allNodes := Nodes{"1": &Node{"test": "foo"}} // :)
singleNode := allNodes["1"]
fmt.Println(Properties(*singleNode).GetString("test")) // :D
}
But it's clearly that is not what you want, you want a struct embedding with a syntax of type aliasing, which is not possible in golang, I think that you should stuck with the your first approach and ignore the the fact the code is redundant and ugly .

Related

Get the type name of a generic struct without type parameters

Say I have a generic struct called foo and I create two objects from it. I can determine the concrete type of each using reflect.TypeOf(), like so:
package main
import (
"fmt"
"reflect"
)
type foo[T any] struct {
data T
}
func main() {
a := foo[string]{"cheese"}
b := foo[int]{42}
fmt.Println(reflect.TypeOf(a))
fmt.Println(reflect.TypeOf(b))
}
// main.foo[string]
// main.foo[int]
What I am interested in is determining just the generic type of these objects (i.e., foo) and not the concrete type (i.e., foo[string] and foo[int]). Is this possible or do I need to manually extract the generic type from these strings (e.g., with regex)?
Edit
Regex might look something like this:
func GetGenericType(x any) string {
// Get type as a string
s := reflect.TypeOf(x).String()
// Regex to run
r := regexp.MustCompile(`\.(.*)\[`)
// Return capture
return r.FindStringSubmatch(s)[1]
}
fmt.Println(GetGenericType(a))
fmt.Println(GetGenericType(b))
// foo
// foo
I've also seen this question but this doesn't answer this question because it gives the concrete type (i.e., main.foo[string]) rather than the generic type (i.e., foo).
Reflection doesn't see the name of the "base" generic type, because at run time that base type doesn't exist.
The relevant passage from the Go spec is Instantiations:
Instantiating a type results in a new non-generic named type; instantiating a function produces a new non-generic function.
So when you write:
b := foo[int]{42}
name := reflect.TypeOf(b).Name()
the name of that type is precisely foo[int].
It's worth noting that the identifier foo without the type parameter list is relevant at compile time, because it prevents you from redeclaring it in the same package. 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, the type name, to it.
TypeDef = identifier [ TypeParameters ] Type .
But instantiations, as defined above, result in a new named type which is different than foo; and at run time when you can use reflection, you deal with instantiations only.
In conclusion, I think your solution with regex is acceptable, until some helper function is added to the stdlib (if ever). Reposting it here for clarity:
func GetGenericType(x any) string {
// Get type as a string
s := reflect.TypeOf(x).String()
// Regex to run
r := regexp.MustCompile(`\.(.*)\[`)
// Return capture
return r.FindStringSubmatch(s)[1]
}
Just keep in mind the difference between Type.String() and Type.Name(): any type can have a string representation, but only named types have a name. (Obviously, right?). So for example if you wrote:
b := &foo[int]{42}
then the type of b is *foo[int], which is an anonymous composite type, and Name() returns an empty string.

Pass pointer as an interface type to the function

I am a new to Go and the behavior below confuses me:
package main
type Contractor struct{}
func (Contractor) doSomething() {}
type Puller interface {
doSomething()
}
func process(p Puller) {
//some code
}
func main() {
t := Contractor{}
process(&t) //why this line of code doesn't generate error
}
In Go some type and pointer to this time conform to the interface? So in my example t and &t are both Pullers?
From the Go spec:
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).
In your case the method set of &t (which is of type *Contractor) is the set of all methods declared with receiver *Contractor or Contractor, so it contains the method doSomething().
This is also discussed in the Go FAQ, and in Go code review comments. Finally, this is covered by many past Stack Overflow questions like this one or that one.

Golang - add "inheritance" to structs

I would like to optimize my code, I have then the following situation:
I have a general struct where only one field gives the specification, let say a cache struct example:
# the main cache struct
type Cache struct {
name string
memory_cache map[string]interface{}
mutex *sync.Mutex
... ...
# common fields
}
# an element stored in the Cache.memory_cache map
type ElementA {
name string
count int64
}
# an element stored in the Cache.memory_cache map
type ElementB {
name string
tags []string
}
My current solution follow the previously definition and I create a cache for each element (it must be so: one cache per element):
var cache_for_element_A Cache{}
var cache_for_element_B Cache{}
But in this way I must always cast the memory_cache when reading, even if I know already what is the content (then no cast-case should be needed).
The following code do what I would like to have, but it defines twice a lot of redundants/commons fields, for this reason I would like to find another solution.
type CacheForA struct {
name string
memory_cache map[string]ElementA{}
mutex *sync.Mutex
... ...
# common fields
}
type CacheForB struct {
name string
memory_cache map[string]ElementB{}
mutex *sync.Mutex
... ...
# common fields
}
Then, is it possible to define a field in the struct (more precisely Cache.memory_cache) that can be further defined when the declaration occurs and without using interface?
Go doesn't have generics, so there's no simple way of doing this, like you would in Java for instance (class Cache<T>()....).
One thing you can do is wrap your cache with a small typed function that just fetches objects from a generic cache and converts the interface to the right type. This just saves you from writing the interface conversion over and over in your code.
type ElemACache struct {
Cache
}
func (c *ElemeACache)Get(key string) ElemeA {
return c.Cache.Get(key).(ElemeA) //of course add checks here
}
Struct embedding is the main thing you are looking for I think:
type Cache struct {
name string
mutex *sync.Mutex
}
type CacheA struct {
Cache
memory_cache map[string]ElementA{}
}
Then you make a type of interface, say "Cacher" that has a set of methods for the things you need to do with your various caches (cacheA, CacheB). Create those methods for CacheA, CacheB, and assertions are only needed only for the return type:
type Cacher interface {
GetItem(string) (interface{}, error)
}
If all your CacheFor types have that GetItem method, the interface will be fulfilled.
Still a fair amount of boilerplate, but this reduces the problem with redundancy in struct definitions. There are code generation tools if you don't want to type the boiler plate.

Is it necessary to use a type assertion to access the values of a type returned by interface?

When I have a function that returns an interface type, the returned value doesn't work as I would expect. That is, it acts strictly as the defined interface, and to access the methods and values not defined in the interface, I have to do a type assertion. Why?
Consider the following sample code:
package main
import (
"fmt"
)
type Frobnicator interface {
Frobnicate()
}
type Foo struct {
Value string
}
func (f *Foo) Frobnicate() {
fmt.Printf("The value is %s\n", f.Value)
}
func fooFactory () Frobnicator {
return &Foo{"chicken"}
}
func main() {
foo := fooFactory( )
foo.Frobnicate()
// foo.Value undefined (type Frobnicator has no field or method Value)
// fmt.Printf("foo value = %s\n", foo.Value)
bar := foo.(*Foo)
fmt.Printf("bar value = %s\n", bar.Value)
}
Is there a better, easier, more idiomatic way to get at foo.Value? Or is a type assertion really the best way?
Not sure what to answer here. Maybe there is a misconception what interface types are. Interface types are absolutely normal types. And you can do with a interface value what the interface says: Invoke the interface methods. For a struct type you may access fields and invoke interface methods as defined by the struct type. So everything is plain and simple: A type allows what it allows, no matter whether interface or struct.
It now happens that a value of interface type may contain some struct value (say). Up to now this is hidden. Type asserting reveals the struct value (and there is no more interface). You may hide an other struct value in the interface (given it implements the right methods) this might not have a Value field. This makes it clear that you cannot access the Value field without a type assertion, because it might not be there.
If you need access to inner value of interface implementation (Value), you must either expose it via interface itself or do a type assertion. That's because nothing in Frobnicator suggests whether it's Foo or some other implementing struct.
It is not different than many other languages. In Java you will have to cast also under similar circumstances.

What's the meaning of interface{}?

I'm new to interfaces and trying to do SOAP request by github
I don't understand the meaning of
Msg interface{}
in this code:
type Envelope struct {
Body `xml:"soap:"`
}
type Body struct {
Msg interface{}
}
I've observed the same syntax in
fmt.Println
but don't understand what's being achieved by
interface{}
Note: Go 1.18 (Q1 2022) does rename interface{} to any (alias for interface{}).
See issue 49884, CL 368254 and commit 2580d0e.
See the last part of this answer.
You can refer to the article "How to use interfaces in Go" (based on "Russ Cox’s description of interfaces"):
What is an interface?
An interface is two things:
it is a set of methods,
but it is also a type
The interface{} type (or any with Go 1.18+), the empty interface is the interface that has no methods.
Since there is no implements keyword, all types implement at least zero methods, and satisfying an interface is done automatically, all types satisfy the empty interface.
That means that if you write a function that takes an interface{} value as a parameter, you can supply that function with any value.
(That is what Msg represents in your question: any value)
func DoSomething(v interface{}) {
// ...
}
func DoSomething(v any) {
// ...
}
Here’s where it gets confusing:
inside of the DoSomething function, what is v's type?
Beginner gophers are led to believe that “v is of any type”, but that is wrong.
v is not of any type; it is of interface{} type.
When passing a value into the DoSomething function, the Go runtime will perform a type conversion (if necessary), and convert the value to an interface{} value.
All values have exactly one type at runtime, and v's one static type is interface{} (or any with Go 1.18+).
An interface value is constructed of two words of data:
one word is used to point to a method table for the value’s underlying type,
and the other word is used to point to the actual data being held by that value.
Addendum: This is were Russ's article is quite complete regarding an interface structure:
type Stringer interface {
String() string
}
Interface values are represented as a two-word pair giving a pointer to information about the type stored in the interface and a pointer to the associated data.
Assigning b to an interface value of type Stringer sets both words of the interface value.
The first word in the interface value points at what I call an interface table or itable (pronounced i-table; in the runtime sources, the C implementation name is Itab).
The itable begins with some metadata about the types involved and then becomes a list of function pointers.
Note that the itable corresponds to the interface type, not the dynamic type.
In terms of our example, the itable for Stringer holding type Binary lists the methods used to satisfy Stringer, which is just String: Binary's other methods (Get) make no appearance in the itable.
The second word in the interface value points at the actual data, in this case a copy of b.
The assignment var s Stringer = b makes a copy of b rather than point at b for the same reason that var c uint64 = b makes a copy: if b later changes, s and c are supposed to have the original value, not the new one.
Values stored in interfaces might be arbitrarily large, but only one word is dedicated to holding the value in the interface structure, so the assignment allocates a chunk of memory on the heap and records the pointer in the one-word slot.
Issue 33232 seems to point out to any as an alias to interface{} in Go 1.18 (Q1 2022)
Russ Cox explains:
'any' being only for constraints is a detail that will be in every writeup of generics - books, blog posts, and so on.
If we think we are likely to allow it eventually, it makes sense to allow it from the start and avoid invalidating all that written material.
'any' being only for constraints is an unexpected cut-out that reduces generality and orthogonality of concepts.
It's easy to say "let's just wait and see", but prescribing uses tends to create much more jagged features than full generality. We saw this with type aliases as well (and resisted almost all the proposed cut-outs, thankfully).
If 'any' is allowed in generics but not non-generic code, then it might encourage people to overuse generics simply because 'any' is nicer to write than 'interface{}', when the decision about generics or not should really be made by considering other factors.
If we allow 'any' for ordinary non-generic usage too, then seeing interface{} in code could serve as a kind of signal that the code predates generics and has not yet been reconsidered in the post-generics world.
Some code using interface{} should use generics. Other code should continue to use interfaces.
Rewriting it one way or another to remove the text 'interface{}' would give people a clear way to see what they'd updated and hadn't. (Of course, some code that might be better with generics must still use interface{} for backwards-compatibility reasons, but it can still be updated to confirm that the decision was considered and made.)
That thread also includes an explanation about interface{}:
It's not a special design, but a logical consequence of Go's type declaration syntax.
You can use anonymous interfaces with more than zero methods:
func f(a interface{Foo(); Bar()}) {
a.Foo()
a.Bar()
}
Analogous to how you can use anonymous structs anywhere a type is expected:
func f(a struct{Foo int; Bar string}) {
fmt.Println(a.Foo)
fmt.Println(a.Bar)
}
An empty interface just happens to match all types because all types have at least zero methods.
Removing interface{} would mean removing all interface functionality from the language if you want to stay consistent / don't want to introduce a special case.
interface{} means you can put value of any type, including your own custom type. All types in Go satisfy an empty interface (interface{} is an empty interface).
In your example, Msg field can have value of any type.
Example:
package main
import (
"fmt"
)
type Body struct {
Msg interface{}
}
func main() {
b := Body{}
b.Msg = "5"
fmt.Printf("%#v %T \n", b.Msg, b.Msg) // Output: "5" string
b.Msg = 5
fmt.Printf("%#v %T", b.Msg, b.Msg) //Output: 5 int
}
Go Playground
There are already good answers here. Let me add my own too for others who want to understand it intuitively:
Interface
Here's an interface with one method:
type Runner interface {
Run()
}
So any type that has a Run() method satisfies the Runner interface:
type Program struct {
/* fields */
}
func (p Program) Run() {
/* running */
}
func (p Program) Stop() {
/* stopping */
}
Although the Program type has also a Stop method, it still satisfies the Runner interface because all that is needed is to have all of the methods of an interface to satisfy it.
So, it has a Run method and it satisfies the Runner interface.
Empty Interface
Here's a named empty interface without any methods:
type Empty interface {
/* it has no methods */
}
So any type satisfies this interface. Because, no method is needed to satisfy this interface. For example:
// Because, Empty interface has no methods, following types satisfy the Empty interface
var a Empty
a = 5
a = 6.5
a = "hello"
But, does the Program type above satisfy it? Yes:
a = Program{} // ok
interface{} is equal to the Empty interface above.
var b interface{}
// true: a == b
b = a
b = 9
b = "bye"
As you see, there's nothing mysterious about it but it's very easy to abuse. Stay away from it as much as you can.
https://play.golang.org/p/A-vwTddWJ7G
It's called the empty interface and is implemented by all types, which means you can put anything in the Msg field.
Example :
body := Body{3}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:3}
body = Body{"anything"}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:"anything"}
body = Body{body}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:main.Body{Msg:"anything"}}
This is the logical extension of the fact that a type implements an interface as soon as it has all methods of the interface.
From the Golang Specifications:
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. The value of an uninitialized variable of
interface type is nil.
A type implements any interface comprising any subset of its methods
and may therefore implement several distinct interfaces. For instance,
all types implement the empty interface:
interface{}
The concepts to graps are:
Everything has a Type. You can define a new type, let's call it T. Let's say now our Type T has 3 methods: A, B, C.
The set of methods specified for a type is called the "interface type". Let's call it in our example: T_interface. Is equal to T_interface = (A, B, C)
You can create an "interface type" by defining the signature of the methods. MyInterface = (A, )
When you specify a variable of type, "interface type", you can assign to it only types which have an interface that is a superset of your interface.
That means that all the methods contained in MyInterface have to be contained inside T_interface
You can deduce that all the "interface types" of all the types are a superset of the empty interface.
An example that extends the excellent answer by #VonC and the comment by #NickCraig-Wood. interface{} can point to anything and you need a cast/type assertion to use it.
package main
import (
. "fmt"
"strconv"
)
var c = cat("Fish")
var d = dog("Bone")
func main() {
var i interface{} = c
switch i.(type) {
case cat:
c.Eat() // Fish
}
i = d
switch i.(type) {
case dog:
d.Eat() // Bone
}
i = "4.3"
Printf("%T %v\n", i, i) // string 4.3
s, _ := i.(string) // type assertion
f, _ := strconv.ParseFloat(s, 64)
n := int(f) // type conversion
Printf("%T %v\n", n, n) // int 4
}
type cat string
type dog string
func (c cat) Eat() { Println(c) }
func (d dog) Eat() { Println(d) }
i is a variable of an empty interface with a value cat("Fish"). It is legal to create a method value from a value of interface type. See https://golang.org/ref/spec#Interface_types.
A type switch confirms i interface type is cat("Fish") . See https://golang.org/doc/effective_go.html#type_switch. i is then reassigned to dog("Bone"). A type switch confirms that i interface’s type has changed to dog("Bone") .
You can also ask the compiler to check that the type T implements the interface I by attempting an assignment: var _ I = T{}. See https://golang.org/doc/faq#guarantee_satisfies_interface and https://stackoverflow.com/a/60663003/12817546.
All types implement the empty interface interface{}. See https://talks.golang.org/2012/goforc.slide#44 and https://golang.org/ref/spec#Interface_types . In this example, i is reassigned, this time to a string "4.3".i is then assigned to a new string variable s with i.(string) before s is converted to a float64 type f using strconv. Finally f is converted to n an int type equal to 4. See What is the difference between type conversion and type assertion?
Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly. See https://golang.org/doc/faq#generics.
Interface is a type which is unknown at compile time
It is a contract between object and the struct type to satisfy with common functionality
or
common functionality acting on different types of struct objects
for example in the below code PrintDetails is a common functionality acting on different types of structs as Engineer,Manager,
Seniorhead
please find the example code
interface examplehttps://play.golang.org/p/QnAqEYGiiF7
A method can bind to any type(int, string, pointer, and so on) in GO
Interface is a way of declear what method one type should have, as long as A type has implement those methods, this can be assigned to this interface.
Interface{} just has no declear of method, so it can accept any type

Resources