Don*_*ark 1 methods function go
我正在开发“Matrix”结构体和相关方法,目的是为了练习 Go。我做了很多方法,但我意识到所有这些方法都可以变成我习惯于C++的函数,而在C++中,如果我创建一个参数是类类型的函数,则该函数不能使用该类的私有变量(信息隐藏)但是,当我使用“Go”构建类似的代码时,函数可以访问结构体的变量。所以我不明白 Go 中的方法和函数有什么不同。使用方法而不是函数是否有任何利润,反之亦然?
第一个是我原来的“Matrix”代码(不是全部)它使用了一种方法“Tr”。它没有问题。
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())
}
Run Code Online (Sandbox Code Playgroud)
第二个是另一个类似的代码。(除了“Tr”部分之外,一切都相同)它仅使用函数。它也没有问题。
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))
}
Run Code Online (Sandbox Code Playgroud)
如果您只想调用函数或方法,没关系,您可以创建一个带有签名的函数,其中接收者是普通的常规参数。不会有任何性能损失(如果方法可以是virtual,则可能会有任何性能损失,但在 Go 中没有虚拟方法)。
优势之一可能是“视觉吸引力”。调用一个方法可以明显看出它属于接收者。我还发现如果使用方法,链式代码更容易理解。
比较这个没有方法的解决方案:
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)))
}
Run Code Online (Sandbox Code Playgroud)
Abs(Center(c))是不是那么直观。但是如果您添加方法而不是使用函数:
func (Circle) Center() Point { return Point{} }
func (Point) Abs() float64 { return 0 }
func main() {
var c Circle
fmt.Println(c.Center().Abs())
}
Run Code Online (Sandbox Code Playgroud)
c.Center().Abs()更容易理解。
如果你想实现接口,方法是必须的。如果接口包含某些方法,则只有具有这些方法的类型才能实现它。请参阅相关:Golang 中为什么需要接口?还应该注意的是,您只能创建在同一包中定义的方法,因此如果您想“武装”来自不同包的类型,则无法“使用”方法。
我将使用方法称为“利润”的一件事是:您不能按名称调用函数,但可以按名称访问和调用方法。有关详细信息,请参阅使用特殊前缀/后缀调用函数。