I have read about what is the difference between functions and methods. I have gone through some previous answers on stack-overflow. However, I could not understand why exactly they are kept different. According to my understanding: whatever can be done using methods can also be done using functions in Go. I know methods are also functions. To further clarify my questions and I have added an example:
package main
import (
"fmt"
)
type Point struct {
a, b int
}
func (p *Point) sumM() int {
return p.a + p.b
}
func sumF(p *Point) int {
return p.a + p.b
}
func (p *Point) mulM(n int) int {
return (p.a + p.b) * n
}
func mulF(p *Point, n int) int {
return (p.a + p.b) * n
}
func main() {
p := Point{2, 3}
fmt.Println("sumM is: ", p.sumM())
fmt.Println("sumF is: ", sumF(&p))
fmt.Println("mulM is: ", p.mulM(2))
fmt.Println("mulF is: ", mulF(&p, 2))
}
where M and F represent method and function respectively.
I want to know if I am missing something; if there is some authentic reasoning behind these different implementations. e.g. pros and cons for each.
Some tips from Golang Methods:
A method is just a function with a receiver argument.
Methods help you write object-oriented style code in Go.
Method calls are much easier to read and understand than function calls.
Methods help you avoid naming conflicts. Since a method is tied to a particular receiver, you can have the same method names on different receiver types.
The thumb of the rule is that do not define methods if:
Dependency on the state is not required
You can perform this function on any type that implements a specific interface which means you don’t need to restrict this function to belong to a specific type.
Related
I'm developing "Matrix" struct and related methods for the purpose of practicing Go.
I made a lot of methods but I realized that all these methods can be changed into functions
I'm used to C++ and in C++, if I make a function whose parameter is a type of class, the function cannot use the class' private variable(information hiding)
However, when I built a similar code using "Go", a function can access a struct's variable.
So I don't get what is different between methods and functions in Go.
Are there any profits using methods rather than functions or vice versa?
First one is my original "Matrix" code(not all of it)
It used a method "Tr".
It doesn't have problems.
package main
import "fmt"
//definition of "Array"
type Array struct{
component [][]float32
row int
col int
}
//constructor of Array, "Ones"; making an array setting all component as one
func Ones(m int, n int) Array{
var a Array
a.component = make([][]float32, m)
a.row=m
a.col=n
for i:=0; i<m; i++{
a.component[i] = make([]float32, n)
for j:=0; j<n; j++{
a.component[i][j]=1
}
}
return a
}
//Tr function; find trace of an Array
func (a Array) Tr() float32{
var sum float32 = 0
for i:=0; i<a.row; i++{
sum += a.component[i][i]
}
return sum
}
func main(){
a := Ones(3,3)
fmt.Println(a.Tr())
}
The second one is another similar code. (Everything is same but "Tr" part)
It used only functions.
It also doesn't have problems.
package main
import "fmt"
//definition of "Array"
type Array struct{
component [][]float32
row int
col int
}
//constructor of Array, "Ones"; making an array setting all component as one
func Ones(m int, n int) Array{
var a Array
a.component = make([][]float32, m)
a.row=m
a.col=n
for i:=0; i<m; i++{
a.component[i] = make([]float32, n)
for j:=0; j<n; j++{
a.component[i][j]=1
}
}
return a
}
//Tr function; find trace of an Array
func Tr(a Array) float32{
var sum float32 = 0
for i:=0; i<a.row; i++{
sum += a.component[i][i]
}
return sum
}
func main(){
a := Ones(3,3)
fmt.Println(Tr(a))
}
If you just want to call the function or method, it doesn't matter, you may create a function with a signature where the receiver is a normal, regular parameter. There won't be any performance penalty (there could be if methods could be virtual, but in Go there are no virtual methods).
One advantage might be the "visual appeal". Calling a method makes it obvious it belongs to the receiver. I also find chained code easier to understand if methods are used.
Compare this solution without methods:
type Circle struct{}
type Point struct{}
func Center(Circle) Point { return Point{} }
func Abs(Point) float64 { return 0 }
func main() {
var c Circle
fmt.Println(Abs(Center(c)))
}
Abs(Center(c)) isn't that intuitive. But if you add methods instead of using functions:
func (Circle) Center() Point { return Point{} }
func (Point) Abs() float64 { return 0 }
func main() {
var c Circle
fmt.Println(c.Center().Abs())
}
c.Center().Abs() is easier to understand.
Methods are a must if you want to implement interfaces. If an interface contains some methods, only types that have those methods can implement it. See related: Why are interfaces needed in Golang? It should also be noted that you may only create methods defined in the same package, so if you want to "arm" a type from a different package, you can't "use" methods.
One thing that I would call "profit" for using methods: you can't call functions by name, but you can access and call methods by name. For details, see Call functions with special prefix/suffix.
I have a function which currently doesn't receive a bool parameter, but then calls another function with a hardcoded bool. We need to remove the hardcoded call and allow a bool to be passed.
I first thought I could try some default parameter - my google searches resulted in that Go apparently doesn't support optional (resp. default) parameter.
So I thought I'd try function overloading.
I found this thread on reddit, which says that it works with a special directive since version 1.7.3:
https://www.reddit.com/r/golang/comments/5c57kg/when_did_function_overloading_get_slipped_in/
I am using 1.8, and still I couldn't get it to work.
I am not even sure I may be allowed to use that directive, but I was speculating that changing the function signature right away may be dangerous as I don't know who uses the function...
Anyway - even with //+overloaded it didn't work
Is there any "idiosyncratic" way or pattern to solve this problem in Go?
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
//result, err := anotherFunc(rpath, true)
return self.Apply(rpath, lpath, true)
}
When I run my test, I get (forgive me for omitting part of the real path to file):
too many arguments in call to self.Apply
have (string, string, bool)
want (string, string)
../remotesystem.go:178: (*RemoteSystem).Apply redeclared in this block
previous declaration at ../remotesystem.go:185
Overloading isn't available in Go. Instead of writing functions with the same name that do different things, it is preferable to be more expressive with what the function does in the function name. In this instance, what would commonly be done is something like this:
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
func (self *RemoteSystem) ApplyDynamic(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
return self.Apply(rpath, lpath, true)
}
Just by the name of the function, you can easily tell what is different and why.
Another example to provide some context (pun intended).
I write a lot of Google App Engine code in Go using go-endpoints. The way to log things is different depending on if you have a context or not. My logging functions ended up like this.
func LogViaContext(c context.Context, m string, v ...interface{}) {
if c != nil {
appenginelog.Debugf(c, m, v...)
}
}
func LogViaRequest(r *http.Request, m string, v ...interface{}) {
if r != nil {
c := appengine.NewContext(r)
LogViaContext(c, m, v...)
}
}
From the Reddit post:
Unicode. I can tell by the pixels.
Go doesn't support function overloading. But it does support using Unicode characters in function names, which allows you to write function names that look like other function names.
The first one is setValue, the second one is setV\u0430lue aka setV\xd0\xb0lue (with CYRILLIC SMALL LETTER A) and the third is setVal\U0001d69ee aka setVal\xf0\x9d\x9a\x9ee (with MATHEMATICAL MONOSPACE SMALL U).
See also:
Does the Go language have function/method overloading? (stackoverflow.com)
Why does Go not support overloading of methods and operators? (golang.org)
Alternative for function overloading in Go? (stackoverflow.com)
I've recently learnt that in the net/http package, there's a pattern of usage that keeps confusing me most. It is function type conversion. It is like this:
(function a) ->convert to-> (type t)
(type t) ->implentments-> (interface i)
So, if there's a function that takes interface i as its parameter, it will invoke the function a, this is the way net/http implements it.
But when I write my own code, I've had many misunderstandings on this pattern. My code goes like this:
package main
import (
"fmt"
)
type eat interface {
eat()
}
type aaa func()
func (op *aaa) eat() {//pointer receiver not right
fmt.Println("dog eat feels good")
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func feelsGood(a eat) {
a.eat()
}
func main() {
b := aaa(dog)
feelsGood(b)
}
//error:aaa does not implement eat (eat method has pointer receiver)
Type aaa has method eat, the same function name and parameter signature, which conforms to the rule of interface eat, but why does it give that error? Does the receiver matter?
Another question is with only a function and type, excluding an interface, the code goes like this:
package main
import (
"fmt"
)
type aaa func()
func (op *aaa) eat() {
op()
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func main() {
obj:=aaa(dog)
obj.eat()
}
//error:cannot call non-function op (type *aaa)
First, is op an anonymous function, regardless of the error?
Second, it works well after I remove the asterisk, but why? op is instance of type aaa, receiver is op, does op stand for function dog()? The http package uses f(w,r) the same way, but it is a little bit of hard to understand. Is op a type, or an instance, or an anonymous function?
It seems like my comprehension of function converting is not right, but I've also checked many posts on Google, and none of them can teach me how to think of it and use it correctly.Thank you!
Question 1:
In Go, for a type T (like aaa in your case), T and *T have different method sets.
So, a value of type T can only access method:
func(t T)Foo() { ... }
While a value of type *T can access both methods:
func(t T)Foo() { ... }
func(t *T)Bar() { ... }
In your case, you have two options. Either you declare the eat method for aaa instead od *aaa:
func (op aaa) eat() {
op()
}
Or you pass the pointer to b to feelsGood:
feelsGood(&b)
Question 2:
Yes, this question is related to the first. But in this case you can access the method because obj.eat() will be short for (&obj).eat().
Your problem here is that you cannot call a function on the function pointer (op *aaa). Your options are to either create the method for aaa instead of *aaa:
func (op aaa) eat() {
op()
}
Or to call the op function on the value and not the pointer:
func (op *aaa) eat() {
(*op)()
}
For the first part of your question: See http://golang.org/doc/faq#different_method_sets which exmplains everything better than I could. You may even search stackoverflow and the golang-nuts mailing list for this question as this comes up very often.
The second is just the same IMHO: aaa doesn't have an eat-method (only *aaa has).
Lambdas work as expected:
func main() {
inc := func(x int) int { return x+1; }
}
However, the following declaration inside a declaration is not allowed:
func main() {
func inc(x int) int { return x+1; }
}
For what reason are nested functions not allowed?
I think there are 3 reasons why this obvious feature isn't allowed
It would complicate the compiler slightly. At the moment the compiler knows all functions are at the top level.
It would make a new class of programmer error - you could refactor something and accidentally nest some functions.
Having a different syntax for functions and closures is a good thing. Making a closure is potentially more expensive than making a function so you should know you are doing it.
Those are just my opinions though - I haven't seen an official pronouncement from the language designers.
Frequently Asked Questions (FAQ)
Why does Go not have feature X?
Every language contains novel features and omits someone's favorite
feature. Go was designed with an eye on felicity of programming, speed
of compilation, orthogonality of concepts, and the need to support
features such as concurrency and garbage collection. Your favorite
feature may be missing because it doesn't fit, because it affects
compilation speed or clarity of design, or because it would make the
fundamental system model too difficult.
If it bothers you that Go is missing feature X, please forgive us and
investigate the features that Go does have. You might find that they
compensate in interesting ways for the lack of X.
What would justify the complexity and expense of adding nested functions? What do yau want to do that you can't do without nested functions? Et cetera.
Here's a way to implement nested functions and functions within nested functions
package main
import "fmt"
func main() {
nested := func() {
fmt.Println("I am nested")
deeplyNested := func() {
fmt.Println("I am deeply nested")
}
deeplyNested()
}
nested()
}
Nested functions are allowed in Go. You just need to assign them to local variables within the outer function, and call them using those variables.
Example:
func outerFunction(iterations int, s1, s2 string) int {
someState := 0
innerFunction := func(param string) int {
// Could have another nested function here!
totalLength := 0
// Note that the iterations parameter is available
// in the inner function (closure)
for i := 0; i < iterations; i++) {
totalLength += len(param)
}
return totalLength
}
// Now we can call innerFunction() freely
someState = innerFunction(s1)
someState += innerFunction(s2)
return someState
}
myVar := outerFunction(100, "blah", "meh")
Inner functions are often handy for local goroutines:
func outerFunction(...) {
innerFunction := func(...) {
...
}
go innerFunction(...)
}
You just have to call it immediately by adding () to the end.
func main() {
func inc(x int) int { return x+1; }()
}
Edit: cannot have function name...so it's just a lambda func getting called right away:
func main() {
func(x int) int { return x+1; }()
}
I wanted to create a function of a certain type. I've found one way to do it, but there must be other, cleaner and nicer ways that do not include using var. What are the alternative ways to declare the function english of type Greeting?
package main
import "fmt"
type Greeting func(name string) string
func (g Greeting) exclamation(name string) string {
return g(name) + "!"
}
var english = Greeting(func(name string) string {
return "Hello, " + name
})
func main() {
fmt.Println(english("ANisus"))
fmt.Println(english.exclamation("ANisus"))
}
In the example above, I can't exchange var english = Greeting... with english := Greeting..., nor can I remove the Greeting(func ...) and just have the func stand alone since then I won't be able to access the exclamation method.
If mentioning var is your main problem, you can drop it easily, by changing = into :=, like this:
english := Greeting(func(name string) string {
return ("Hello, " + name);
})
But you don't even have to cast your function into Greeting. The spec says this about function types:
A function type denotes the set of all functions with the same parameter and result types.
And this about type identity:
Two function types are identical if they have the same number of parameters and result values, corresponding parameter and result types are identical, and either both functions are variadic or neither is. Parameter and result names are not required to match.
This means that each function has its own function type. If two functions have the same signature (parameter and result types), they share one function type. By writing type Greeting func... you're just giving a name to a particular function type, not defining a new one.
So the following code works, and I hope shows the right way to work with function types in Go:
package main
import "fmt"
type Greeting func(name string) string
func say(g Greeting, n string) { fmt.Println(g(n)) }
func french(name string) string { return "Bonjour, " + name }
func main() {
english := func(name string) string { return "Hello, " + name }
say(english, "ANisus")
say(french, "ANisus")
}
Notice that I also dropped semicolon and parenthesis from your english function. Go developers don't use these punctuations if they don't have to.
UPDATE: Now that you've provided a sample code I can clearly understand the problem.
For this purpose your code is good enough and there are not much other ways of doing it. If you like you can cast just before calling the method:
english := func(name string) string { return "Hello, " + name }
Greeting(english).exclamation("ANisus")
But I'm not sure this is an improvement. I'm just saying that for what you want to do there does not seem to be other ways to write the code.
That is, if we don't want to change your types. I mean, the whole idea of calling a method on a function type seems a little weird. Not that it's wrong, but a little rare. Another way of achieving the same effect in a more usual way is through a struct type and having a field for the function. Something like this:
package main
import "fmt"
type Greeting struct {
say func(name string) string
}
func newGreeting(f func(string) string) *Greeting {
return &Greeting{say: f}
}
func (g *Greeting) exclamation(name string) string { return g.say(name) + "!" }
func main() {
english := &Greeting{say: func(name string) string {
return "Hello, " + name
}}
french := newGreeting(func(name string) string {
return "Bonjour, " + name
})
fmt.Println(english.exclamation("ANisus"))
fmt.Println(french.exclamation("ANisus"))
}
Here english and french show two different ways of coding the same thing. Again, I'm not saying that this is the better solution, but a more usual and more flexible way of achieving the same effect.
Trying to separate issues here,
type Greeting func(string) string
func english(name string) string {
return return "Hello, " + name
}
func main() {
var g Greeting
g = english
fmt.Println(g("ANisus"))
}
Is the way to declare the function english of type Greeting. Notice Greeting is not used in the definition of english, so this may not meet your requirement of declaring a function of a specific type. Otherwise, sorry, there is no way in Go to define a function of a specific (that is, separately defined) type. It might be nice to type something like,
english := Greeting {
return return "Hello, " + name
}
but no, there is no way in Go. The declaration of english can't use Greeting, and must repeat the function signature. Instead the requirement that english is of type Greeting is made only in the assignment
g = english
g is declared of type Greeting. If english isn't the same type, the line won't compile.
Beyond the issue of repeating the type signature--the issues of methods, for example--it's not clear if you're still looking for other ways to organize the functionality of your example. It can certainly be done other ways. A bigger example though, maybe posed as a separate question, would help.