how to call child method in parent method? [duplicate] - go

This question already has an answer here:
Go embedded struct call child method instead parent method
(1 answer)
Closed 7 years ago.
package main
import "fmt"
type Super struct{}
func (super *Super) name() string {
return "Super"
}
func (super *Super) WhoAmI() {
fmt.Printf("I'm %s.\n", super.name())
}
type Sub struct {
Super
}
func (sub *Sub) name() string {
return "Sub"
}
func main() {
sub := &Sub{Super{}}
sub.WhoAmI()
}
I want to get "I'm Sub", but I get "I'm Super" instead.
I already know sub.WhoAmI will call sub.Super.WhoAmI, but I still want to know if there is a way to get "I'm Sub". In Python when I write following code:
class Super(object):
def name(self):
return "Super"
def WhoAmI(self):
print("I'm {name}".format(name=self.name()))
class Sub(Super):
def name(self):
return "Sub"
if __name__ == "__main__":
sub = Sub()
sub.WhoAmI()
I can get "I'm Sub".

Embedding is not subclassing. There are no superclasses or subclasses in Go. Sub here is not a "child" of Super. It contains a Super. You can't do you're trying to do. You need to organize your code in a different way so that it's not needed.
For example, here (playground) is a more natural way to do this in Go:
package main
import "fmt"
type Namer interface {
Name() string
}
type Super struct{}
func (sub *Super) Name() string {
return "Super"
}
type Sub struct{}
func (sub *Sub) Name() string {
return "Sub"
}
func WhoAmI(namer Namer) {
fmt.Printf("I'm %s.\n", namer.Name())
}
func main() {
sub := &Sub{}
WhoAmI(sub)
}
Rather than focus on classes (which Go doesn't have), this focuses on interfaces. It's not a question of what things are, it's a question of what they can do. This is a very powerful approach to programming, and in practice is often much more flexible and less error-prone than inheritance abstractions.

Think of functions in Go as if they all belong to a single namespace. Go really doesn’t have classes, methods, or inheritance, so what you’re attempting will never work the way you intend.
To put it another way, when you define a function like this:
func (f *Foo) DoStuff()
You can imagine it really being defined as:
func DoStuff(f *Foo)
So you might notice why Go chose to call the name function on your Super struct—it was the only function signature that matched. (Note that in your WhoAmI function super is defined as super *Super so Go matches it up with the corresponding function of the same type.)
As for how you might do this the Go way, try using interfaces:
http://play.golang.org/p/8ELw-9e7Re
package main
import "fmt"
type Indentifier interface {
WhoAmI() string
}
type A struct{}
func (a *A) WhoAmI() string {
return "A"
}
type B struct{}
func (b *B) WhoAmI() string {
return "B"
}
func doSomething(x Indentifier) {
fmt.Println("x is a", x.WhoAmI())
}
func main() {
doSomething(&A{})
doSomething(&B{})
}

Related

Methods dispatch using interface in Go

How is actually methods in Go get dispatched if we use interface, static(compile time) or dynamic(run time). Let consider this code:
package main
import "fmt"
type ICat interface {
Meow()
Walk()
Run()
}
func NewCat(name string) ICat {
return &cat{
name:name,
}
}
type cat struct {
name string
}
func (c *cat) Meow() {
fmt.Print("Meowwwwwwwww")
}
func (c *cat) Walk() {
fmt.Print("Walk")
}
func (c *cat) Run() {
fmt.Print("Run")
}
type IAnimal interface{
DoSound()
}
type animal struct {
cat ICat
}
func New() IAnimal {
return &animal{
cat:NewCat("bobby"),
}
}
func (a *animal) DoSound() {
a.cat.Meow()
}
func main() {
i := New()
i.DoSound()
}
Go Playground: https://play.golang.org/p/RzipDT6FAC9
How actually those methods defined in those interface got dispatched?, I use this style of development to implement interface segregation and separation of concern between data and behaviour. My other concern is the perf. Some said it's statically dispatched at compile time, while other said it's dynamically dispatched at run time.
We cannot know at compile time what the dynamic type of an interface value will be, A call through an interface must use dynamic dispatch. Instead of a direct call, the compiler must generate code to obtain the address of the method from the type descriptor, then make an indirect call to that address.

How can I implement the same function for pointers to different structs?

Suppose I have a lot of different structs, but they all share a common field, such as "name". For example:
type foo struct {
name string
someOtherString string
// Other fields
}
type bar struct {
name string
someNumber int
// Other fields
}
Further on in the program, I repeatedly encounter the situation where I get pointers to these structs (so *foo, *bar, etc.) and need to perform operations depending on whether the pointer is nil or not, basically like so:
func workOnName(f *foo) interface{} {
if (f == nil) {
// Do lots of stuff
} else {
// Do lots of other stuff
}
// Do even more stuff
return something
}
This function, which only uses name, is the same across all structs. If these were not pointers, I know I could write a common interface for each struct that returns the name and use that as the type. But with pointers, none of this has worked. Go either complains while compiling, or the nil check doesn't work and Go panics. I haven't found anything smarter than to copy/paste the exact same code for every struct that I have, so basically to implement all the functions:
func (f *foo) workOnName() interface{}
func (b *bar) workOnName() interface{}
func (h *ham) workOnName() interface{}
// And so on...
Is there a way to do this better, i.e. to only implement a simple function (or even better, no function at all) for all my structs and simply write the complicated stuff once, for all the structs?
Edit: Thank you to the answers so far, but simply using an interface of the type:
func (f foo) Name() string {
return f.name
}
for some interface that provides Name() does not work, because the pointer is not recognized as nil. See this playground: https://play.golang.org/p/_d1qiZwnMe_f
You can declare an interface which declares a function returning a name:
type WithName interface {
Name() string
}
In order to implement that interface, you types (foo, bar, etc) need to have that method - not just the field, the method.
func (f foo) Name() string {
return f.name
}
Then, workOnName needs to receive a reference of that interface:
func workOnName(n WithName) interface{} {
if (n == nil || reflect.ValueOf(n).isNil()) {
// Do lots of stuff
} else {
// Do lots of other stuff
}
// Do even more stuff
return something
}
Keep in mind that the parameter n WithName is always treated as a pointer, not an object value.
I think that's the case for reflect.
Something like:
package main
import (
"fmt"
"reflect"
)
func SetFieldX(obj, value interface{}) {
v := reflect.ValueOf(obj).Elem()
if !v.IsValid() {
fmt.Println("obj is nil")
return
}
f := v.FieldByName("X")
if f.IsValid() && f.CanSet() {
f.Set(reflect.ValueOf(value))
}
}
func main() {
st1 := &struct{ X int }{10}
var stNil *struct{}
SetFieldX(st1, 555)
SetFieldX(stNil, "SSS")
fmt.Printf("%v\n%v\n", st1, stNil)
}
https://play.golang.org/p/OddSWT4JkSG
Note that IsValid checks more than just obj==nil but if you really want to distinguish cases of nil pointers and non-struct objects - you are free to implement it.

GO - method redeclared error

Rule is, methods can be defined only on named type and pointer to named type.
For the below code,
package main
type Cat struct {
}
func (c Cat) foo() {
// do stuff_
}
func (c *Cat) foo() {
// do stuff_
}
func main() {
}
compiler gives error:
main.go:10: method redeclared: Cat.foo
method(Cat) func()
method(*Cat) func()
Above code defines,
method foo() for named type(Cat) and
method foo() for pointer to named type(*Cat).
Question:
For GO compiler, Why methods defined for different type is considered
same?
In Go, receivers are a kind of syntactic sugar. The actual, runtime signature of function (c Cat) foo() is foo(c Cat). The receiver is moved to a first parameer.
Go does not support name overloading. There can be only one function of with name foo in a package.
Having said the statements above, you see that there would be two functions named foo with different signatures. This language does not support it.
You cannot do that in Go. The rule of thumb is to write a method for a pointer receiver and Go will use it whenever you have a pointer or value.
If you still need two variants, you need name the methods differently.
For example, you can model some feline behavior like this:
package main
import (
"fmt"
)
type Growler interface{
Growl() bool
}
type Cat struct{
Name string
Age int
}
// *Cat is good for both objects and "object references" (pointers to objects)
func (c *Cat) Speak() bool{
fmt.Println("Meow!")
return true
}
func (c *Cat) Growl() bool{
fmt.Println("Grrr!")
return true
}
func main() {
var felix Cat // is not a pointer
felix.Speak() // works :-)
felix.Growl() // works :-)
var ginger *Cat = new(Cat)
ginger.Speak() // works :-)
ginger.Growl() // works :-)
}

Method vs Functions Usage golang

I know differences between func and method. But I am confusing for usages between:
prod:=Product{"title","brand","model"}
prod.Add()
or:
prod:=Product{"title","brand","model"}
products.Add(&prod) // products is package
These are two distinct cases, one which is a method belongs to Product instance and one is a global function belongs to products package.
type Product struct {
Title string
Brand string
Model string
}
// This method add value to a field in Product
func (p *Product) Add(field, value string) {
switch field {
case "Title":
p.Title = value
case "Brand":
p.Brand = value
case "Model":
p.Model = value
}
}
The above provide a method to add value to itself as an instance of Product, i.e.
product1 := &Product{}
product1.Add("Title", "first_title")
The second case is a public function exposed from a product package. In this case, an instance (or a pointer) of a Product must be supplied as an argument.
package products
func Add(p *Product, field, value string) {
// Same switch-case as above
}
Add function then can be used from any other package.
package main
import (
"path/to/products"
)
type Product struct {
// ...
}
func main() {
product1 := &Product{}
products.Add(product1, "Title", "first_title")
Normally in your scenario, the first approach is preferred since it encapsulates the functionality of managing its attributes to itself.
The second scenario might be seen as a "class method approach" (for those coming from OOP like Python or Java) where the package is similar to class and the exposed functions similar to class methods which are more generic and can be used across many types which implement the same interface, like so:
package products
// where p is a Product interface
func Add(p Product, field, value string) {
// Same switch-case as above
}
type Product interface {
someMethod()
}
And from another package:
package main
import (
"path/to/products"
)
type Car struct {
Title string
Brand string
Model string
}
type Ship struct {
// ...
}
type Airplane struct {
// ...
}
// All types implement `Product` and can be used in `products.Add`
func (c *Car) someMethod() {}
func (s *Ship) someMethod() {}
func (a *Airplane) someMethod() {}
func main() {
plane := &Airplane{}
products.Add(plane, "Model", "Boeing-747")
}
This is expected as per the spec:
The type of a method is the type of a function with the receiver as first argument.
See https://golang.org/ref/spec#Method_declarations
So when you declare the Add method on Product, you get a function that accepts a pointer to a Product as its first argument. So you end up with
func (p *Product) Add()
being translated to
func Add(p *Product)
So both your calls are valid and end up doing the same
Extending the fantastic answer by #Danilo:
package main
import "fmt"
type T struct {
i int
}
func (t *T) F() {
t = &T{1}
fmt.Println(t.i)
}
func F(t *T) {
fmt.Println(t.i)
}
func main() {
t := T{2}
(&t).F()
F(&t)
}
The type of the method func (t *T) F() is the type of the function func F(t *T) with the receiver (t *T) as first argument.

Private fields and methods for a struct

In the following test code I would like to have both mytype and the doPrivate method private, so that only members of mytype can access it, but not other types\functions in the scope of the mypackage package.
Can I do this in golang?
package mypackage
type mytype struct {
size string
hash uint32
}
func (r *mytype) doPrivate() string {
return r.size
}
func (r *mytype) Do() string {
return doPrivate("dsdsd")
}
Fields size and hash as well as the doPrivate method should be encapsulated and no other type should have access to them.
In Go, an identifier that starts with a capital letter is exported from the package, and can be accessed by anyone outside the package that declares it.
If an identifier starts with a lower case letter, it can only be accessed from within the package.
If you need members in a type to only be accessed by members of that type, you then need to place that type and its member functions in a separate package, as the only type in that package.
That's not how "privacy" works in Go: the granularity of privacy is the package.
If you really want only the members of mytype to access some fields, then you must isolate the struct and the functions in their own package.
But that's not the usual practice. Whether Go is OOP or not is debatable but clearly the practice isn't to encapsulate the code by a struct like you seem to want to do. Usually a package is small enough to be coherent: if you don't want to access fields from within the package, don't access them.
You can create an interface with the method you wish to expose and only access the object when wrapped into that interface.
package main
type mytype struct {
size string
hash uint32
}
// interface for exposed methods
type myinterface interface {
do() string
}
// constructor (optional)
func newMytype(size string, hash uint32) myinterface {
return &mytype{size, hash}
}
func (r *mytype) doPrivate() string {
return r.size
}
func (r *mytype) do() string {
return r.doPrivate()
}
func main() {
// with constructor
t := newMytype("100", 100)
t.do()
// t.doPrivate() // t.doPrivate undefined (type myinterface has no field or method doPrivate)
// without constructor
t2:= myinterface(&mytype{"100", 100})
t2.do()
// t.doPrivate() // t.doPrivate undefined (type myinterface has no field or method doPrivate)doPrivate)
}
https://play.golang.org/p/awjIIj8Kwms
You cannot do this in Go. Visibility is on a per package level only. But you may split your package into two.
In one module there can be any number of packages.
Public/Private works only across one package.
All public fields, methods and functions starts with uppercase char.
All private fields, methods and functions starts with lowercase char.
To add package to your module or program just create a lowercase folder and add package name to all files inside. Here is the example.
./main.go
./foo/foo.go
./foo/MyStruct.go
file ./foo/foo.go:
package foo
import "fmt"
func SomePublicFuncInFoo() {
somePrivateFuncInFoo()
}
func somePrivateFuncInFoo() {
fmt.Println("somePrivateFuncInFoo call")
}
file ./foo/MyStruct.go:
package foo
import "fmt"
type MyStruct struct {
MyPublicField string // starts with uppercase char
myPrivateField string // starts with lowercase char
}
func NewMyStruct(publicField string, privateField string) *MyStruct {
return &MyStruct{
MyPublicField: publicField,
myPrivateField: privateField,
}
}
func (self *MyStruct) SomePublicMethod() {
self.privateMethod()
}
func (self *MyStruct) privateMethod() {
fmt.Println("MyStruct", self.MyPublicField, self.myPrivateField)
}
file ./main.go:
package main
import (
"fmt"
"{your-module-name}/foo" // this line should be added by your IDE
)
func main() {
foo.SomePublicFuncInFoo()
myStruct := foo.NewMyStruct("string1", "string2")
fmt.Println("myStruct.MyPublicField=", myStruct.MyPublicField)
myStruct.SomePublicMethod()
}
You can have private variables and functions in Go, but the trick is that you simply don't define them in the struct. Bind them to the call stack of a closure, and simply don't return them.
package main
import (
"fmt"
)
type mytype struct {
Do func() string
}
func MyType(size string, hash uint32) mytype {
doPrivate := func() string {
return size
}
return mytype{
Do: func() string {
return doPrivate()
},
}
}
func main() {
instance := MyType("100", 100)
fmt.Println(instance.Do())
}

Resources