Golang 方法

优质
小牛编辑
153浏览
2023-12-01

Go 语言中的方法其实就是一个特殊函数,只不过这个函数是和某种属性类型绑定在一起的而已

Go 语言中的方法 一般用于函数和结构体绑定在一起,让结构体除了能够保存数据外还能具备某些行为

将函数和数据类型绑定的格式

只需要在函数名称前面加上(接收者 数据类型),即可将函数和某种数据类型绑定在一起

func (接收者 数据类型)方法名称(形参列表)(返回值列表){
  方法体
}

示例:给结构体添加一个方法,此时结构体除了可以保存数据,还具备说出自己名字和年龄的行为

package main
import "fmt"
// 1.定义一个结构体
type Person struct {
	name string
	age int
}
// 2.定义一个函数, 并将这个函数和Person结构体绑定在一起
func (p Person)say()  {
	fmt.Println("my name is", p.name, "my age is", p.age)
}
func main() {
	// 3.创建一个结构体变量
	per := Person{"lnj", 33}
	// 4.利用结构体变量调用和结构体绑定的方法
	// 调用时会自动将调用者(per)传递给方法的接收者(p)
	// 所以可以在方法内部通过p方法结构体变量的属性
	per.say()
}

方法和函数异同

方法的数据类型也是函数类型,所以也可以定义变量保存(作为参数返回值等)

package main
import "fmt"
type Person struct {
  name string
  age int
}
// 定义一个方法
func (p Person)say()  {
  fmt.Println("say方法")
}
// 定义一个函数
func say()  {
  fmt.Println("say函数")
}
func main() {
  p := Person{"lnj", 33}
  fmt.Printf("%T\n", p.say) // func()
  fmt.Printf("%T\n", say) // func()

  // 定义一个保存没有形参没有返回值的函数类型变量
  var fn func()
  // 利用函数类型变量保存一个方法
  fn = p.say
  // 利用函数类型变量调用一个方法
  fn()

  // 利用函数类型变量保存一个函数
  fn = say
  // 利用函数类型变量调用一个函数
  fn()
}

方法只能通过绑定类型的变量调用,函数可以直接调用

package main
import "fmt"
type Person struct {
   name string
   age int
}
// 定义一个方法
func (p Person)say()  {
   fmt.Println("my name is", p.name, "my age is", p.age)
}
// 定义一个函数
func test()  {
   fmt.Println("test")
}
func main() {
   per := Person{"lnj", 33}
   per.say() // 方法只能通过绑定类型的变量调用
   //say() // 编译报错, 不能直接调用
   test() // 编译通过, 可以直接调用
}

方法的接收者可以看做就是函数的一个形参

package main
import "fmt"
type Person struct {
   name string
   age int
}
// 定义一个方法
func (p Person)say()  {
   fmt.Println("my name is", p.name, "my age is", p.age)
}
// 定义一个函数
func test(p Person)  {
   fmt.Println("my name is", p.name, "my age is", p.age)
}
func main() {
   per := Person{"lnj", 33}
   per.say() // my name is lnj my age is 33
   test(per) // my name is lnj my age is 33
}

既然可以看做形参,那么自然也具备形参的特点(值传递和地址传递)

package main
import "fmt"
type Person struct {
   name string
   age int
}
// 接收者是一个变量
func (p Person)setName(name string)  {
   p.name = name
}
// 接收者是一个指针
func (p *Person)setAge(age int)  {
   p.age = age
}
func main() {
   per := Person{"lnj", 33}
   fmt.Println(per) // {lnj 33}
   // 值传递, 方法内部修改不会影响方法外部
   per.setName("zs")
   fmt.Println(per) // {lnj 33}
   p := &per
   // 地址传递, 方法内部修改会影响方法外部
   (*p).setAge(18)
   fmt.Println(per) // {lnj 18}
}

地址传递的几种调用方式

package main
import "fmt"
type Person struct {
   name string
   age int
}
// 接收者是一个变量
func (p Person)setName(name string)  {
   p.name = name
}
// 接收者是一个指针
func (p *Person)setAge(age int)  {
   p.age = age
}
func main() {
   per := Person{"lnj", 33}
   // 方式一: 先拿到指针,然后再通过指针调用
   p := &per
   (*p).setAge(18)
   fmt.Println(per) // {lnj 18}
   // 方式二: 直接利用变量调用, 底层会自动获取变量地址传递给接收者
   per.setAge(66)
   fmt.Println(per) // {lnj 66}
}