视频来源:B站《golang入门到项目实战 [2022最新Go语言教程,没有废话,纯干货!]》
文章为自己整理的学习笔记,侵权即删,谢谢支持!
文章目录
一 golang方法简介
go语言没有面向对象的特性,也没有类对象的概念。但是,可以使用结构体来模拟这些特性,我们都知道面向对象里面有类方法等概念。我们也可以声明一些方法,属于某个结构体。
Go中的方法,是一种特殊的函数,定义于结构体struct之上(与struct关联、绑定),被称为struct的接受者(receiver)。通俗的讲,方法就是有接收者的函数。
1.1 语法
type mytype struct{}
func (recv mytype) my_method(para) retrun_type {}
func (recv *mytype) my_method(para) return_type {}
mytype:定义的一个结构体
recv:接受该方法的结构体(receiver)
my_method:方法名称
para:参数列表
return_type:返回值类型
从语法格式可以看出,一个方法和一个函数非常相似,只不过多了一个接受类型。
1.2 实例演示
package main
import "fmt"
type Person struct {
name string
}
func (per Person) eat() {
fmt.Println(per.name + " eating....")
}
func (per Person) sleep() {
fmt.Println(per.name + " sleep....")
}
func main() {
var per Person
per.name = "tom"
per.eat()
per.sleep()
}
运行结果:
tom eating....
tom sleep....
1.3 注意事项
- 方法的receiver type并非一定要是struct类型,type定义的
类型别名、slice、map、channel、func类型等都可以。 - 结构体struct结合它的方法就等价于面向对象中的类。只不过struct可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。
- 方法有两种接收类型:
(T Type)和(T *Type),它们之间有区别。 - 方法就是函数,所以Go中没有方法重载(overload)的说法,也就是说同一个类型中的所有方法名必须都唯一。
- 如果receiver是一个指针类型,则会自动解除引用。
- 方法和类型是分开的,意味着实例的行为和数据存储是分开的,但是它们通过receiver建立起关联关系。
二 golang方法接收者类型
结构体实例有值类型和指针类型,而方法的接收者是结构体,那么也有值类型和指针类型。区别就是接收者是否复制结构体副本。
值类型复制,指针类型不复制。
2.1 值类型结构体和指针类型结构体
先看一段代码:
package main
import "fmt"
type Person struct {
name string
}
func main() {
p1 := Person{name: "tom"}
fmt.Printf("p1: %T\n", p1)
p2 := &Person{name: "tom"}
fmt.Printf("p2: %T\n", p2)
}
运行结果:
p1: main.Person
p2: *main.Person
从运行结果,我们可以看出p1是值类型,p2是指针类型。
下面看一个传参结构体的例子:
package main
import "fmt"
type Person struct {
name string
}
func showPerson(per Person) {
fmt.Printf("per: %p\n", &per)
per.name = "kite"
fmt.Printf("per: %v\n", per)
}
func showPerson2(per *Person) {
fmt.Printf("per: %p\n", per)
// (*per).name
per.name = "kite"
fmt.Printf("per: %v\n", per)
}
func main() {
p1 := Person{name: "tom"}
fmt.Printf("p1: %p\n", &p1)
showPerson(p1)
fmt.Printf("p1: %v\n", p1)
fmt.Println("---------------------")
p2 := &Person{name: "tom"}
fmt.Printf("p2: %p\n", p2)
showPerson2(p2)
fmt.Printf("p2: %v\n", p2)
}
运行结果:
p1: 0xc000050230
per: 0xc000050240
per: {kite}
p1: {tom}
---------------------
p2: 0xc000050270
per: 0xc000050270
per: &{kite}
p2: &{kite}
从运行结果,我们看到p1是值传递,拷贝了副本,地址发生了改变;而p2是指针类型,地址没有改变。
2.2 方法的值类型和指针类型接收者
值类型和指针类型接收者本质上和函数传参道理相同。
package main
import "fmt"
type Person struct {
name string
}
func (per Person) showPerson() {
fmt.Printf("per: %p\n", &per)
per.name = "kite"
fmt.Printf("per: %v\n", per)
}
func (per *Person) showPerson2() {
fmt.Printf("per: %p\n", per)
per.name = "kite"
fmt.Printf("per: %v\n", per)
}
func main() {
p1 := Person{name: "tom"}
fmt.Printf("p1: %p\n", &p1)
p1.showPerson()
fmt.Printf("p1: %v\n", p1)
fmt.Println("---------------------")
p2 := &Person{name: "tom"}
fmt.Printf("p2: %p\n", p2)
p2.showPerson2()
fmt.Printf("p2: %v\n", p2)
}
运行结果:
p1: 0xc000050230
per: 0xc000050240
per: {kite}
p1: {tom}
---------------------
p2: 0xc000050270
per: 0xc000050270
per: &{kite}
p2: &{kite}
三 方法和函数区别
-
调用方式不一样
函数的调用方式:
函数名(实参列表)
方法的调用方式:变量.方法名(实参列表) -
对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然
-
对于方法(如 struct 的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以
练习
① 编写结构体(MethodUtils),编程一个方法,方法不需要参数,在方法中打印一个 10*8 的矩形,在 main 方法中调用该方法。
package main
import (
"fmt"
)
type Methodutiles struct {
}
func (mu Methodutiles) Print() {
for i := 1; i <= 10; i++ {
for j := 1; j <= 8; j++ {
fmt.Print("*")
}
fmt.Println()
}
}
func main() {
var mu Methodutiles
mu.Print()
}
运行结果:
********
********
********
********
********
********
********
********
********
********
② 定义小小计算器结构体(Calcuator),实现加减乘除四个功能
实现形式 1:分四个方法完成;
实现形式 2:用一个方法搞定。
实现形式1:
type Calcuator struct {
Num1 float64
Num2 float64
}
// 实现形式1:
func (cal *Calcuator) getSum() float64 {
return cal.Num1 + cal.Num2
}
func (cal *Calcuator) getSub() float64 {
return cal.Num1 - cal.Num2
}
func (cal *Calcuator) getPro() float64 {
return cal.Num1 * cal.Num2
}
func (cal *Calcuator) getQuo() float64 {
return cal.Num1 / cal.Num2
}
实现形式2:
type Calcuator struct {
Num1 float64
Num2 float64
}
func (cal *Calcuator) getRes(operator byte) float64 {
res := 0.0
switch operator {
case '+':
res = cal.Num1 + cal.Num2
case '-':
res = cal.Num1 - cal.Num2
case '*':
res = cal.Num1 * cal.Num2
case '/':
res = cal.Num1 / cal.Num2
default:
fmt.Println("运算符输入错误")
}
return res
}
本文是Go语言学习笔记,详细介绍了Go中的方法,包括方法的语法、实例演示、注意事项,以及方法接收者类型的区别。文章讨论了值类型结构体和指针类型结构体作为接收者时的不同行为,并对比了方法与函数的调用差异。最后,给出了两个练习题,以加深对方法应用的理解。
527

被折叠的 条评论
为什么被折叠?



