tux*_*21b 84
据我所知,目前:函数是"全局的",这意味着我不必导入包来使用函数,它们总是在那里.方法绑定到包.它是否正确?
不,那不对.内置程序包中只有几个功能始终可用.其他一切都需要进口.
术语"方法"提出了面向对象的编程.在OOP语言(例如C++)中,您可以定义一个"类",它封装了属于一起的数据和函数.类中的这些函数称为"方法",您需要该类的实例来调用此类方法.
在Go中,术语基本相同,尽管Go不是经典意义上的OOP语言.在Go中,接收接收器的函数通常被称为方法(可能仅仅因为人们习惯于OOP的术语).
所以,例如:
func MyFunction(a, b int) int {
return a + b
}
// Usage:
// MyFunction(1, 2)
Run Code Online (Sandbox Code Playgroud)
但
type MyInteger int
func (a MyInteger) MyMethod(b int) int {
return a + b
}
// Usage:
// var x MyInteger = 1
// x.MyMethod(2)
Run Code Online (Sandbox Code Playgroud)
Sal*_*ali 16
Tux的答案很棒,但是我希望通过使用Go的方法来增加它struct(因为这是我经常使用它的地方).因此,我们假设你想构建一些东西来计算三角形上的各种方法.你从一开始struct:
type Triangle struct {
a, b, c float64
}
Run Code Online (Sandbox Code Playgroud)
然后你想添加一些函数来计算周长和平方:
func valid(t *Triangle) error {
if t.a + t.b > t.c && t.a + t.c > t.b && t.b + t.c > t.a {
return nil
}
return errors.New("Triangle is not valid")
}
func perimeter(t *Triangle) (float64, error) {
err := valid(t)
if err != nil {
return -1, err
}
return t.a + t.b + t.c, nil
}
func square(t *Triangle) (float64, error) {
p, err := perimeter(t)
if err != nil {
return -1, err
}
p /= 2
s := p * (p - t.a) * (p - t.b) * (p - t.c)
return math.Sqrt(s), nil
}
Run Code Online (Sandbox Code Playgroud)
现在你得到了你的工作计划Go Playground.在这种情况下,您的函数接受一个参数(指向三角形的指针)并执行某些操作.在OOP中,人们可能创建了一个类,然后添加了方法.我们可以看到我们的struct作为带有字段的类,现在我们添加方法:
func (t *Triangle) valid() error {
if t.a + t.b > t.c && t.a + t.c > t.b && t.b + t.c > t.a {
return nil
}
return errors.New("Triangle is not valid")
}
func (t *Triangle) perimeter() (float64, error) {
err := t.valid()
if err != nil {
return -1, err
}
return t.a + t.b + t.c, nil
}
func (t *Triangle) square() (float64, error) {
p, err := t.perimeter()
if err != nil {
return -1, err
}
p /= 2
s := p * (p - t.a) * (p - t.b) * (p - t.c)
return math.Sqrt(s), nil
}
Run Code Online (Sandbox Code Playgroud)
我们有一个完整的working example.
请注意,它看起来非常像对象的方法.
小智 9
这里详细解释了它们 - https://anil.cloud/2017/01/26/golang-functions-methods-simplified/
Go中的函数遵循以下语法:
func FunctionName(Parameters...) ReturnTypes...
Run Code Online (Sandbox Code Playgroud)
例:
func add(x int, y int) int
Run Code Online (Sandbox Code Playgroud)
执行:
add(2,3)
Run Code Online (Sandbox Code Playgroud)
方法类似于函数,但附加到类型(称为接收器).官方指南指出"方法是具有特殊接收器参数的函数".接收器出现在func关键字和方法名称之间.方法的语法是:
func (t ReceiverType) FunctionName(Parameters...) ReturnTypes...
Run Code Online (Sandbox Code Playgroud)
例:
func (t MyType) add(int x, int y) int
Run Code Online (Sandbox Code Playgroud)
执行:
type MyType string
t1 := MyType("sample")
t1.add(1,2)
Run Code Online (Sandbox Code Playgroud)
现在让我们把指针带到表中.Go lang是按值传递的,意味着参数的新副本被传递给每个函数/方法调用.要通过引用传递它们,您可以使用指针.
参数/参数列表中带指针的函数语法.
func FunctionName(*Pointers...,Parameters...) ReturnTypes...
Run Code Online (Sandbox Code Playgroud)
例
func add(t *MyType, x int, y int) int
Run Code Online (Sandbox Code Playgroud)
执行:
type MyType string
t1 := MyType("sample")
add(&t1,4,5)
Run Code Online (Sandbox Code Playgroud)
类似地,对于方法,接收器类型可以是指针.带指针的方法语法(作为接收器)
func (*Pointer) FunctionName(Parameters...) ReturnTypes...
Run Code Online (Sandbox Code Playgroud)
例
func (t *MyType) add(x int, y int) int
Run Code Online (Sandbox Code Playgroud)
执行:
type MyType string
t1 := MyType("sample")
t1.add(2,3)
Run Code Online (Sandbox Code Playgroud)
请注意,我们仍然可以编写t1.add()来使用指针接收器执行该方法(即使't1'不是指针),Go会将其解释为(&t1).add().类似地,也可以使用指针调用带有值接收器的方法,在这种情况下,Go会将p.add()解释为(*p).add()(其中'p'是指针).这仅适用于方法而不适用于功能.
具有指针接收器的方法对于获得类似"Java"的行为非常有用,其中该方法实际上修改接收器指向的值而不是其副本.