Go method receivers take a type along with a variable name for the type, example:
type MyFloat float64
func (x MyFloat) Abs() float64 {
if x < 0 {
return float64(-x)
}
return float64(x)
}
func main() {
f := MyFloat(-math.Sqrt2)
fmt.Println(f.Abs())
}
The receiver takes "x" along with the type receiving the method. What is the significance of the name 'x'. Since i am able to invoke the method on any instance of MyFloat ( not just on the one named as x ) why do i have to specify the x ? Since the receiver is a Type or a reference to a type why not simply take the type or the pointer alone like this
func (MyFloat) Abs() float64 {
if this < 0 {
return float64(-this)
}
return float64(this)
}
My assumption is instead of this in Java golang allows any name? Is that so ?
Your assumption is exact: the receiver has to be explicitly named in a method definition. It avoids any ambiguity. In your example, how could the Go compiler guess that x is the receiver?
Note that using "self" or "this" or "me" as the receiver name is considered as bad style in go. The name should be short - one letter is fine. See more information at https://code.google.com/p/go-wiki/wiki/CodeReviewComments#Receiver_Names
It's a design choice.
Java use this, Go-lang choose another mechanic.
In Go, it's legal to make the receiver a pointer or not.
Let's see:
func (t Type) Id() { return t }
func (t *Type) IdPointer() { return t }
What if Go use Java's design?
It will became:
func (Type) Id() { return this }
func (*Type) IdPointer() { return this }
Firstly, it is confused that what (*Type) is.
Secondly, this can also be a pointer or a value. Also confused.
But, anyway, you can design Go-lang like this.
It is a choice after all.
I think you are not using correctly you should use it in a struct.Where the receiver makes a reference to the struct's fields.
For example:
package main
import "fmt"
type Decimal struct {
first float64
}
func (x Decimal) out() float64 {
return x.first
}
func main() {
var start Decimal
start.first = 10.8
show := start.out()
fmt.Println(show)
}
Related
Edit: This is not the right way to use interfaces in Go. The purpose of this question is for me to understand how empty interfaces work in Go.
If all types in Go implement interface{} (empty interface), why can't I access the name field in the Cat and Dog structs? How can I get access to the name field of each struct through the function sayHi()?
package main
import (
"fmt"
)
func sayHi(i interface{}) {
fmt.Println(i, "says hello")
// Not understanding this error message
fmt.Println(i.name) // i.name undefined (type interface {} is interface with no methods)
}
type Dog struct{
name string
}
type Cat struct{
name string
}
func main() {
d := Dog{"Sparky"}
c := Cat{"Garfield"}
sayHi(d) // {Sparky} says hello
sayHi(c) // {Garfield} says hello
}
An interface{} is a method set, not a field set. A type implements an interface if it's methods include the methods of that interface. Since empty interface doesn't have any methods, all types implement it.
If you need to access a field, you have to get the original type:
name, ok:=i.(Dog).name
This will recover the name if i is a Dog.
Alternatively, implement a getName() function for both Dog and Cat, and then they will both implement the following interface:
type NamedType interface {
getName() string
}
Then you can rewrite your function as:
func sayHi(i NamedType) {
fmt.Println(i.getName())
}
You can't do that because interface values don't do that.
What interface values do—regardless of the interface type itself; it doesn't matter if the interface type is empty or not—is that they hold two things:
the concrete type of some value (or no type); and
the value of that concrete type (or no value).
So if some variable v or expression e has type I where I is an interface type, then you can, with some syntax, inspect either or both of these two "fields". They're not struct fields so you can't just use v.type, but you can do this:
switch v.(type) {
case int: // the value in v has type int
case *float64: // the value in v has type float64
// etc
}
The .(type) in a switch means let me look at the type field.
Getting the actual value is harder, because Go more or less requires that you check the type first. In your case, you know that i holds either a Dog or a Cat, so you can write:
var name string
switch i.(type) {
case Dog: name = i.(Dog).name
case Cat: name = i.(Cat).name
default: panic("whatever 'i' is, it is not a Dog or Cat")
}
fmt.Println(name)
This is pretty clumsy, and there are lots of ways to make it less clumsy, but that's always the first step: figure out what the type is.
Well, sometimes there's a step before the first step: figure out whether the variable has anything at all in it. You do this with:
if i == nil {
...
}
Note, however, that if i has some typed value in it, and the type can hold nil pointers, the value part of i can be nil and yet i == nil will be false. That's because i does have a type in it.
var i interface{}
var p *int
if i == nil {
fmt.Println("i is initially nil")
}
if p == nil {
fmt.Println("p is nil")
}
i = p
if i != nil {
fmt.Printf("i is now not nil, even though i.(*int) is %v\n", i.(*int))
}
(try this on the Go playground).
This usually isn't the right way to use interface
Most often—there are exceptions—we don't even try to look at the type of some interface. Instead, we define an interface that provides methods—functions we can call—that do something we need done. See Burak Serdar's answer in which the interface type has a getName method. Then, instead of trying to figure out which of some limited set of types someone gave us, we just say:
name := i.getName()
to invoke the getName method on the underlying concrete value. If i holds a Dog, that calls func (Dog) getName() string, which you'll need to define. If i holds a Cat, it calls func (Cat) getName() string. If you decide to add to your collection a type named Bird, you can define func (Bird) getName() string, and so on.
(Usually, the methods would be exported too: GetName, rather than getName.)
Like you say, interface{} is an empty interface. How can you assume that something "empty" has a name field in it (fmt.Println(i.name))? You can't. In fact, go doesn't support fields in interfaces, only methods.
What you can do (and there are, of course, many solutions), is to define an interface (let's call it Pet) which has a method returning the pet's name:
type Pet interface {
getName() string
}
Then you can receive this interface (its object) in the sayHi function and use it to print the pet's name:
func sayHi(i Pet) {
fmt.Println(i.getName())
}
Now, in order to be able to pass Dog or Cat to sayHi(), both of these structs have to implement the interface. So, define the getName() methods for them:
func (d Dog) getName() string {
return d.name
}
func (c Cat) getName() string {
return c.name
}
And that's it.
It can also be implemented using switch type as below-
package main
import (
"fmt"
)
func sayHi(i interface{}) {
fmt.Println(i, "says hello")
switch x := i.(type) {
case Dog:
fmt.Println(x.name)
case Cat:
fmt.Println(x.name)
}
}
type Dog struct {
name string
}
type Cat struct {
name string
}
func main() {
d := Dog{"Sparky"}
c := Cat{"Garfield"}
sayHi(d) // {Sparky} says hello
sayHi(c) // {Garfield} says hello
}
Playground link - https://go.dev/play/p/p4s3_jmmbGJ
Version of Go
go version go1.11 darwin/amd64
Code 1:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
//func GotU(t esc);
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
Code 2:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
Code 3:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e *esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
The outputs:
code 1 output: 9
code 2 output: 9
code 3 cannot be compiled due to a type mismatch
Since only func (e esc)GotU() implemented, why should both pieces of code work and deliver the same result?
It's kind of confusing for me to pass a pointer of struct to that function (TestFunc) to get the same answer.
The last code snippet has implemented a method receiver of pointer type. This will consider the situation if you want to modify the value of receiver.
func (e *esc) GotU() {
e.i = 10
}
In above case Since you are passing pointer type receiver on a method which is implementing the interface.
type myintf interface {
GotU()
}
So you need to pass address of struct in TestFunc. This is the reason you are getting type mismatch error, because you are passing variable of esc type while your method requires variable of *esc.
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
Working example on Go playground
In Golang there are two ways to pass a method receiver.
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
For programmers unaccustomed to pointers, the distinction between
these two examples can be confusing, but the situation is actually
very simple. When defining a method on a type, the receiver (s in the
above examples) behaves exactly as if it were an argument to the
method. Whether to define the receiver as a value or as a pointer is
the same question, then, as whether a function argument should be a
value or a pointer. There are several considerations
First, and most important, does the method need to modify the receiver? If it does, the receiver must be a pointer. (Slices and maps act as references, so their story is a little more subtle, but for instance to change the length of a slice in a method the receiver must still be a pointer.) In the examples above, if pointerMethod modifies the fields of s, the caller will see those changes, but valueMethod is called with a copy of the caller's argument (that's the definition of passing a value), so changes it makes will be invisible to the caller.
The difference between the 1st and second version is, that you pass the struct directly in one version and the pointer to the struct in the other version. In this case these programs work the same, as the pointer also includes the all defined funcs on the struct.
But this does not work the other way around. You define the method GotU on the pointer receiver. The struct does not know about this func. If you would call
TestFunc(&test)
in the third program, it would compile but work differently than the other two: The output is: "10"
As the GotU is defined on the pointer receiver test is passed as reference and the modifications persist. In the other programs test is passed as value, i.e. it is copied, the copy is modified in GotU. When the func exits, the copy is discarded and the old version is still the same as before.
There are multiple answers/techniques to the below question:
How to set default values to golang structs?
How to initialize structs in golang
I have a couple of answers but further discussion is required.
One possible idea is to write separate constructor function
//Something is the structure we work with
type Something struct {
Text string
DefaultText string
}
// NewSomething create new instance of Something
func NewSomething(text string) Something {
something := Something{}
something.Text = text
something.DefaultText = "default text"
return something
}
Force a method to get the struct (the constructor way).
From this post:
A good design is to make your type unexported, but provide an exported constructor function like NewMyType() in which you can properly initialize your struct / type. Also return an interface type and not a concrete type, and the interface should contain everything others want to do with your value. And your concrete type must implement that interface of course.
This can be done by simply making the type itself unexported. You can export the function NewSomething and even the fields Text and DefaultText, but just don't export the struct type something.
Another way to customize it for you own module is by using a Config struct to set default values (Option 5 in the link). Not a good way though.
One problem with option 1 in answer from
Victor Zamanian is that if the type isn't exported then users of your package can't declare it as the type for function parameters etc. One way around this would be to export an interface instead of the struct e.g.
package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
Name string
Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
return candidate{name, 0} // enforce the default value here
}
Which lets us declare function parameter types using the exported Candidate interface.
The only disadvantage I can see from this solution is that all our methods need to be declared in the interface definition, but you could argue that that is good practice anyway.
There is a way of doing this with tags, which
allows for multiple defaults.
Assume you have the following struct, with 2 default
tags default0 and default1.
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Now it's possible to Set the defaults.
func main() {
ptr := &A{}
Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...
Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}
Here's the complete program in a playground.
If you're interested in a more complex example, say with
slices and maps, then, take a look at creasty/defaultse
From https://golang.org/doc/effective_go.html#composite_literals:
Sometimes the zero value isn't good enough and an initializing constructor is necessary, as in this example derived from package os.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
What about making something like this:
// Card is the structure we work with
type Card struct {
Html js.Value
DefaultText string `default:"html"` // this only works with strings
}
// Init is the main function that initiate the structure, and return it
func (c Card) Init() Card {
c.Html = Document.Call("createElement", "div")
return c
}
Then call it as:
c := new(Card).Init()
I found this thread very helpful and educational. The other answers already provide good guidance, but I wanted to summarize my takeaways with an easy to reference (i.e. copy-paste) approach:
package main
import (
"fmt"
)
// Define an interface that is exported by your package.
type Foo interface {
GetValue() string // A function that'll return the value initialized with a default.
SetValue(v string) // A function that can update the default value.
}
// Define a struct type that is not exported by your package.
type foo struct {
value string
}
// A factory method to initialize an instance of `foo`,
// the unexported struct, with a default value.
func NewFoo() Foo {
return &foo{
value: "I am the DEFAULT value.",
}
}
// Implementation of the interface's `GetValue`
// for struct `foo`.
func (f *foo) GetValue() string {
return f.value
}
// Implementation of the interface's `SetValue`
// for struct `foo`.
func (f *foo) SetValue(v string) {
f.value = v
}
func main() {
f := NewFoo()
fmt.Printf("value: `%s`\n", f.GetValue())
f.SetValue("I am the UPDATED value.")
fmt.Printf("value: `%s`\n", f.GetValue())
}
One way to do that is:
// declare a type
type A struct {
Filed1 string
Field2 map[string]interface{}
}
So whenever you need a new variable of your custom defined type just call the NewA function also you can parameterise the function to optionally assign the values to the struct fields
func NewA() *A {
return &A{
Filed1: "",
Field2: make(map[string]interface{}),
}
}
for set default values in Go structs we use anonymous struct:
Person := struct {
name string
age int
city string
}{
name: "Peter",
age: 21,
city: "Noida",
}
fmt.Println(Person)
Structs
An easy way to make this program better is to use a struct. A struct is a type which contains named fields. For example we could represent a Circle like this:
type Circle struct {
x float64
y float64
r float64
}
The type keyword introduces a new type. It's followed by the name of the type (Circle), the keyword struct to indicate that we are defining a struct type and a list of fields inside of curly braces. Each field has a name and a type. Like with functions we can collapse fields that have the same type:
type Circle struct {
x, y, r float64
}
Initialization
We can create an instance of our new Circle type in a variety of ways:
var c Circle
Like with other data types, this will create a local Circle variable that is by default set to zero. For a struct zero means each of the fields is set to their corresponding zero value (0 for ints, 0.0 for floats, "" for strings, nil for pointers, …) We can also use the new function:
c := new(Circle)
This allocates memory for all the fields, sets each of them to their zero value and returns a pointer. (*Circle) More often we want to give each of the fields a value. We can do this in two ways. Like this:
c := Circle{x: 0, y: 0, r: 5}
Or we can leave off the field names if we know the order they were defined:
c := Circle{0, 0, 5}
type Config struct {
AWSRegion string `default:"us-west-2"`
}
I am trying to learn Go, and I found a good resource here.
The example given on method overloading is reproduced below:
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Employee struct {
Human
company string
}
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
sam.SayHi()
}
Is it possible to call the "base" struct's (Human's) methods, eg. sam.Human.SayHi() Downcasting doesn't work (because there is no type hierarchy right?)
You can access the embedded struct of a parent struct by calling the member of the parent with the name of the embedded type's name. That's a mouthful, so it's probably easier to demonstrate it.
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
sam.SayHi() // calls Employee.SayHi
sam.Human.SayHi() // calls Human.SayHi
Outputs
Hi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX
Hi, I am Sam you can call me on 111-888-XXXX
This is the nearest approximation to sane polymorphism with both plain and pure virtual functions that I have found thus far. By the very nature of Go's design and the goal at hand, it is ugly but effective.
package main
import (
"fmt"
)
type I interface {
foo(s string) // Our "pure virtual" function
bar()
}
type A struct {i I}
type B struct {A}
type C struct {B}
// fk receivers, this is a "member function" so I'll use OO nomenclature
func (this *A) init(i I) {
this.i = i // the i contains (internal) pointers to both an object and a type
}
func (this *A) bar() {
this.i.foo("world")
}
func (this *B) foo(s string) {
fmt.Printf("hello %s\n", s)
}
func (this *C) foo(s string) {
fmt.Printf("goodbye cruel %s\n", s)
}
func main() {
var i I
b := &B{}
b.init(b) // passing b as the parameter implicitly casts it to an I interface object
b.bar()
c := &C{}
c.init(c)
c.bar() // c is a pointer to C, so Golang calls the correct receiver
i = b
i.bar()
i = c
i.bar() // Internally, i contains pointers to the C object and the C type,
// so that the correct receiver is called
}
https://play.golang.org/p/4qBfmJgyuHC
In real OO languages, each object of a class with any virtual functions must have a pointer to a virtual function table or a least type that maps to it. So adding an interface member to the base (embedded) struct only wastes an additional machine word for the pointer that will just point to its self.
Alternatively, we could remove the I interface member from A and the have pure virtual member function just accept the implementation as an argument.
type I interface {
foo(s string)
bar(i I)
}
type A struct {}
type B struct {A}
type C struct {B}
func (this *A) bar(i I) {
i.foo("world")
}
https://play.golang.org/p/9gvaCuqmHS8
But at this point, foo is no longer a pure virtual function, API users could pass any value whose type implements I, and the whole OO concept is broken. The object pointer portion of the I interface passed to bar doesn't need to be the same as this, but then again we didn't need to pass that same value using an init() function, but at least only an API user in the same package would be allowed to set it.
At this point, we have transitioned to the Go way of doing things: compositional programming with dependency injection. This is what Ken Thompson and the other designers thought was a better way to go -- at least for their stated goals. While it is vastly inferior in MANY respects, it does create many advantages and I won't argue those points that here.
In Go, you can pass functions as parameters like callFunction(fn func). For example:
package main
import "fmt"
func example() {
fmt.Println("hello from example")
}
func callFunction(fn func) {
fn()
}
func main() {
callFunction(example)
}
But is it possible to call a function when it's a member of a struct? The following code would fail, but gives you an example of what I'm talking about:
package main
import "fmt"
type Example struct {
x int
y int
}
var example Example
func (e Example) StructFunction() {
fmt.Println("hello from example")
}
func callFunction(fn func) {
fn()
}
func main() {
callFunction(example.StructFunction)
}
(I know what I'm trying to do in that example is a little odd. The exact problem I have doesn't scale down to a simple example very well, but that's the essence of my problem. However I'm also intrigued about this from an academic perspective)
Methods (which are not "members of a struct" but methods of any named type, not only structs) are first class values. Go 1.0.3 didn't yet implemented method values but the tip version (as in the comming Go 1.1) has support method values. Quoting the full section here:
Method values
If the expression x has static type T and M is in the method set of type T, x.M is called a method value. The method value x.M is a function value that is callable with the same arguments as a method call of x.M. The expression x is evaluated and saved during the evaluation of the method value; the saved copy is then used as the receiver in any calls, which may be executed later.
The type T may be an interface or non-interface type.
As in the discussion of method expressions above, consider a struct type T with two methods, Mv, whose receiver is of type T, and Mp, whose receiver is of type *T.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
var pt *T
func makeT() T
The expression
t.Mv
yields a function value of type
func(int) int
These two invocations are equivalent:
t.Mv(7)
f := t.Mv; f(7)
Similarly, the expression
pt.Mp
yields a function value of type
func(float32) float32
As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.
As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mv is equivalent to (&t).Mv.
f := t.Mv; f(7) // like t.Mv(7)
f := pt.Mp; f(7) // like pt.Mp(7)
f := pt.Mv; f(7) // like (*pt).Mv(7)
f := t.Mp; f(7) // like (&t).Mp(7)
f := makeT().Mp // invalid: result of makeT() is not addressable
Although the examples above use non-interface types, it is also legal to create a method value from a value of interface type.
var i interface { M(int) } = myVal
f := i.M; f(7) // like i.M(7)
Go 1.0 does not support the use of bound methods as function values. It will be supported in Go 1.1, but until then you can get similar behaviour through a closure. For example:
func main() {
callFunction(func() { example.StructFunction() })
}
It isn't quite as convenient, since you end up duplicating the function prototype but should do the trick.
I fixed your compile errors.
package main
import "fmt"
type Example struct {
x, y float64
}
var example Example
func (e Example) StructFunction() {
fmt.Println("hello from example")
}
func callFunction(fn func()) {
fn()
}
func main() {
callFunction(example.StructFunction)
}
Output:
hello from example
To add to #zzzz great answer (and the one given at https://golang.org/ref/spec#Method_values) here is an example that creates a method value from a value of an interface type.
package main
import "fmt"
type T struct{}
func (T) M(i int) { fmt.Println(i) }
func main() {
myVal := T{}
var i interface{ M(int) } = myVal
f := i.M
f(7) // like i.M(7)
}