Skip to content

Go语言方法

方法定义

Go 语言的方法非常纯粹, 可以看作特殊类型的函数, 其显式地将对象实例或指针作为函数的第一个参数, 并且参数名可以自己指定, 而不强制要求一定是 thisself 。这个对象实例或指针称为方法的接收者(reciever)。

为命名类型定义方法的语法格式如下:

go
// 类型方法接收者是值类型
func (t TypeName) MethodName (ParamList ) (Returnlist) {
	//method body
}

// 类型方法接收者是指针
func (t *TypeName) MethodName (ParamList) (Returnlist) {
	//method body
}

说明:

t 是接收者或者叫接收器变量,官方建议使用接收器类型名 TypeName 的 第一个小写字母,而不是 self 、 this 之类的命名。例如, Socket 类型的接收器变量应该命名为 s, Connector 类型的接收器变量应该命名为 c 等; TypeName 为命名类型的类型名; MethodName 为方法名,是一个自定义标识符; ParamList 是形参列表; ReturnList 是返回值列表; 接收者的定义和普通变量、函数参数等一样,前面是变量名,后面是接收者类型。

创建方法和使用

切片方法

go
package main

import "fmt"

type SliceInt []int

// 面向对象
func (s SliceInt) Sum() int {
	sum := 0
	for _, i := range s {
		sum += i
	}

	return sum
}

// 面向过程   这个函数和上面方法等价
func SliceIntSum(s SliceInt) int {
	sum := 0
	for _, i := range s {
		sum += i
	}

	return sum
}

func main() {
	var s SliceInt = []int{1, 2, 3, 4, 5}
	fmt.Println(s.Sum()) // 面向对象的方法
	fmt.Println(SliceIntSum(s)) // 面向过程的方法
}

结构体方法

处理球体时,假设您要计算其表面积和体积。在这种情况下,非常适合使用结构体和方法集。通过使用方法集,您只需创建一次计算代码,就可将其重用于任何球体。要创建这个方法集,可声明结构体 Sphere 巳再声明两个将结构体 Sphere 作为接收者的方法。

go
package main

import (
	"fmt"
	"math"
)

type Sphere struct {
	Radius float64
}

/* 这里声明了计算球体表面积和体积的方法,并像通常那样定义函数签名。唯一不同的
是添加了一个表示接收者的参数,这里是一个指向 Sphere  实例的指针
*/
func (s *Sphere) SurfaceArea() float64 {
	return float64(4) * math.Pi * (s.Radius * s.Radius)
}

func (s *Sphere) Volume() float64 {
	radiusCubed := s.Radius * s.Radius * s.Radius
	return (float64(4) / float64(3)) * math.Pi * radiusCubed
}

// 方法接收者参数类型为值引用
func (s Sphere) ChageRadiusValue(r float64) float64 {
	s.Radius = r
	return r
}

// 方法接收者参数类型为指针
func (s *Sphere) ChageRadiusPoint(r float64) float64 {
	s.Radius = r
	return r
}

func main() {

	s := &Sphere{
		Radius: 5,
	}
	fmt.Println(s.SurfaceArea())
	fmt.Println(s.Volume())

	r := 1.0
	s.ChageRadiusValue(r) // 方法接收者参数类型为值引用时不会改变原始值
	fmt.Println(s.Radius) // 5
	s.ChageRadiusPoint(r) // 方法接收者参数类型为指针时会改变原始值
	fmt.Println(s.Radius) // 1
}

指针和值之间的差别很微妙,但选择使用指针还是值这一点很简单:

  • 如果需要修改原始结构体,就使用指针;
  • 如果需要操作结构体,但不想修改原始结构体,就使用值.