1

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))
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
  • 1
    There aint no such thing as methods in Go. There are only functions. I guess this answers the question. – Markus W Mahlberg Oct 01 '19 at 06:21
  • 4
    From [here](https://tour.golang.org/methods/1): "A method is a function with a special receiver argument." – Clément Oct 01 '19 at 06:32
  • 2
    from the spec https://golang.org/ref/spec#Method_sets –  Oct 01 '19 at 06:50
  • 1
    @MarkusWMahlberg funny how the Go Language Specification has sections about Method Declarations, Method Expressions, Method Values, and Method Sets then. – hobbs Oct 01 '19 at 07:02
  • @hobbs See above. "A method is a function with a special argument". A function, at the end of the day. or, from the specs, exploring method sets a bit deeper: "A method is a function with a receiver". Still a function. – Markus W Mahlberg Oct 01 '19 at 07:32
  • 1
    @MarkusWMahlberg We're not saying a method is not a function, even your quote says method is a thing, so it's harsh to say they don't exist. – icza Oct 01 '19 at 07:35
  • @icza In the context of the question? ;) – Markus W Mahlberg Oct 01 '19 at 07:36

1 Answers1

6

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.

icza
  • 389,944
  • 63
  • 907
  • 827
  • Also, the namespace for methods is the type they are defined on, not the package namespace. So it's possible to define two distinct methods named Foo in a package, but not two functions named Foo. – Peter Oct 01 '19 at 10:18
  • @Peter True, but just as easily we could name 2 different `Foo` functions `Type1Foo` and `Type2Foo` if needed. – icza Oct 01 '19 at 10:19