我正在出于练习Go的目的而开发“ Matrix”结构和相关方法。 我做了很多方法,但是我意识到所有这些方法都可以变成函数 我已经习惯了C ++,在C ++中,如果我制作了一个参数为类类型的函数,该函数将无法使用该类的私有变量(信息隐藏) 但是,当我使用“ Go”构建类似的代码时,函数可以访问结构的变量。 所以我没有得到Go中方法和函数之间的区别。 使用方法而不是功能会产生任何利润,反之亦然吗?
第一个是我原始的“矩阵”代码(不是全部) 它使用方法“ 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())
}
第二个是另一个类似的代码。 (除“ 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))
}
答案 0 :(得分:4)
如果只想调用函数或方法,没关系,您可以创建一个带有签名的函数,其中接收者是正常的常规参数。不会有任何性能损失(方法可能是virtual,但在Go中没有虚拟方法)。
一个优势可能是“视觉吸引力”。调用方法很明显它属于接收方。如果使用方法,我还会发现链接代码更容易理解。
比较不带方法的此解决方案:
select id,name,max(total_score) over (partition by name) max_score from (
select id,name,sum(score) as total_score from YOURTABLE
group by id,name
) t
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))
func (Circle) Center() Point { return Point{} }
func (Point) Abs() float64 { return 0 }
func main() {
var c Circle
fmt.Println(c.Center().Abs())
}
更容易理解。
如果要实现接口,则必须使用方法。如果接口包含某些方法,则只有具有那些方法的类型才能实现它。请参阅相关内容:Why are interfaces needed in Golang?还应注意,您只能创建在同一程序包中定义的方法,因此,如果您要“武装”来自其他程序包的类型,则不能“使用”方法。 / p>
使用方法时,我会称其为“利润”:您不能按名称调用函数,但是可以按名称访问和调用方法。有关详细信息,请参见Call functions with special prefix/suffix。