Methods
Go does not have classes. However, you can define methods on types. Go 没有类。但是,您可以在类型上定义方法。
A method is a function with a special receiver argument. 方法是具有特殊接收者参数的函数。
The receiver appears in its own argument list between the func keyword and the method name. 接收者出现在它自己的参数列表中,位于 func 关键字和方法名称之间。
In this example, the Abs method has a receiver of type Vertex named v. 在此示例中, Abs 方法有一个名为 v 的 Vertex 类型的接收者。
package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
//三角函数
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := Vertex{6, 8}
fmt.Println(v.Abs())
}
Methods are functions
Remember: a method is just a function with a receiver argument. 请记住:方法只是一个带有接收者参数的函数。
Here's Abs written as a regular function with no change in functionality. 这里的 Abs 编写为常规函数,功能没有变化。
Methods and pointer indirection 方法和间接指针
Functions that take a value argument must take a value of that specific type: 采用值参数的函数必须采用该特定类型的值:
var v Vertex fmt.Println(AbsFunc(v)) // OK fmt.Println(AbsFunc(&v)) // Compile error! while methods with value receivers take either a value or a pointer as the receiver when they are called: 而具有值接收者的方法在调用时将值或指针作为接收者:
var v Vertex fmt.Println(v.Abs()) // OK p := &v fmt.Println(p.Abs()) // OK In this case, the method call p.Abs() is interpreted as (*p).Abs(). 在这种情况下,方法调用 p.Abs() 被解释为 (*p).Abs() 。
package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func AbsFunc(v Vertex) float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs())
fmt.Println(AbsFunc(v))
p := &Vertex{4, 3}
fmt.Println(p.Abs())
fmt.Println(AbsFunc(*p))
}
Choosing a value or pointer receiver
There are two reasons to use a pointer receiver. 使用指针接收器有两个原因。
The first is so that the method can modify the value that its receiver points to. 第一个是该方法可以修改其接收者指向的值。
The second is to avoid copying the value on each method call. This can be more efficient if the receiver is a large struct, for example. 第二个是避免在每次方法调用时复制值。例如,如果接收器是一个大型结构,这会更有效。
In this example, both Scale and Abs are methods with receiver type *Vertex, even though the Abs method needn't modify its receiver. 在此示例中, Scale 和 Abs 都是接收者类型为 *Vertex 的方法,即使 Abs 方法不需要修改其接收者。 tips:通过指针接收器可以修改
type Vertex struct {
X, Y float64
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := &Vertex{3, 4}
fmt.Printf("Before scaling: %+v, Abs: %v\n", v, v.Abs())
v.Scale(5)
fmt.Printf("After scaling: %+v, Abs: %v\n", v, v.Abs())
}
interface接口
An interface type is defined as a set of method signatures. 接口类型被定义为一组方法签名。
A value of interface type can hold any value that implements those methods. 接口类型的值可以包含实现这些方法的任何值
package main
import (
"fmt"
"math"
)
type Abser interface {
Abs() float64
}
func main() {
var a Abser
v := Vertur{4, 5}
a = &v
fmt.Println(a.Abs())
}
type Vertur struct {
X, Y float64
}
func (v *Vertur) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
Interfaces are implemented implicitly 接口是隐式实现的
A type implements an interface by implementing its methods. There is no explicit declaration of intent, no "implements" keyword. 类型通过实现其方法来实现接口。没有明确的意图声明,没有“实施”关键字。
Implicit interfaces decouple the definition of an interface from its implementation, which could then appear in any package without prearrangement. 隐式接口将接口的定义与其实现分离,然后可以在没有预先安排的情况下出现在任何包中
结构体必需实现接口中的所有方法才可以具备接口的类型
type I interface {
sum() string
}
type T struct {
S string
}
// This method means type T implements the interface I,
// but we don't need to explicitly declare that it does so.
func (t T) sum() string{
fmt.Println(t.S)
return t.S
}
func main() {
var i I = T{"hello"}
var myString = i.sum()
fmt.Println(myString)
}