网页设计与网站建设,办网站怎么赚钱,wordpress下载安装,互联网营销的五个手段本节内容是面向对象的核心与基础#xff0c;很重要。 注意#xff1a;由于导包语句已经在19讲#xff08;笔记19#xff1a;面向对象的引入#xff09;展示过了#xff0c;所以这里就不展示了。
一、方法的定义与细节
方法是与特定类型#xff08;通常是结构体#x…本节内容是面向对象的核心与基础很重要。 注意由于导包语句已经在19讲笔记19面向对象的引入展示过了所以这里就不展示了。
一、方法的定义与细节
方法是与特定类型通常是结构体关联的函数。方法可以操作该类型的实例并且可以使用其字段。定义方法时需要指定一个接收者receiver这使得方法能够访问该接收者的属性。语法如下
func (receiver TypeName) MethodName(parameters) returnList {// 方法体
}receiver是接收者的名称类型是你想要关联的自定义类型通常是结构体。 MethodName是方法的名称。 parameters是方法接受的参数。 returnList是返回值类型列表。 首先在utils中定义一个结构体和一个方法
type Circle struct {Radius float64
}// 定义一个方法计算圆的面积
// 1. 方法中参数名字随便起
// 2. 方法 Area 和结构体 Circle绑定必须在同包中定义
func (c Circle) Area() float64 {return 3.14 * c.Radius * c.Radius
}然后在main中调用
func main() {// 创建一个 Circle 实例circle : utils.Circle{Radius: 5}// 调用方法area : circle.Area()// 输出结果fmt.Printf(Area: %.2f\n, area)
}一些细节 1.如果其他类型的变量调用area一定会报错。 2.结构体对象传入方法area中属于值传递和参数传递一致。 3.receiver的类型是你想要关联的自定义类型。 4.如果某个自定义类型实现了返回string名字为String()的方法如果是同包内调用s可以小写那么fmt包的Printf或Println函数打印该类型时会自动调用String()。 对于前两点首先在utils中定义另一个方法来演示值传递
// 定义一个方法演示值传递
func (c Circle) SetRadius(newRadius float64) {c.Radius newRadiusfmt.Printf(Inside Radius: %.2f\n, c.Radius)
}然后在main文件中调用
type test struct {a int
}func main() {// 创建一个 Circle 实例circle : utils.Circle{Radius: 5}// 调用方法area : circle.Area()fmt.Printf(Area: %.2f\n, area)// 1. 如果其他类型变量调用 area 一定会报错// 下面的代码将导致编译错误//t : test{}// t.area() // 这行会报错因为 radius 不是 Circle 类型// 2. 结构体对象传入方法 Area 中属于值传递circle2 : utils.Circle{Radius: 10}fmt.Printf(Old Radius: %.2f\n, circle2.Radius)// 调用 SetRadius 方法尝试修改半径circle2.SetRadius(15)fmt.Printf(New Radius: %.2f\n, circle2.Radius) // 仍然是 10
}OK如果我就想在SetRadius内改变radius呢那肯定是用指针了但方法比数组指针简单将SetRadius中的Circle前加上*即可因为编译器会自动处理结构体指针所以在main中的代码无需改动 对于第三点receiver的类型是你想要关联的自定义类型这也就是说基本类型不能作为方法中的接收类型读者可自行尝试这里不做赘述。 对于第四点首先在utils内定义String()
func (p Person) String() string {str : fmt.Sprintf(name%s,age%v,sex%s, p.Name, p.Age, p.Sex)return str
}然后在main中调用
func main() {p : utils.Person{Name: 李华, Age: 30, Sex: 女}fmt.Printf(%v\n, p) // 使用格式化字符串fmt.Println(p) // 直接打印
}这个String方法呢也是定义结构体时常用的以便输出结构体信息。这里我提一个问题如果定义了Person的别名打印其实例还会自动调用String()吗验证很简单读者可自行尝试这里不做赘述。
二、方法与函数的区别
方法函数和其他类型的关系绑定到特定类型独立于任何类型语法func (receiver ReceiverType) MethodName(parameters) returnTypefunc FunctionName(parameters) returnType调用方式通过类型的实例调用 instance.MethodName()直接调用 FunctionName()作用域可以访问绑定类型的字段只能访问传入的参数指定类型是否需要和传入类型一致不需要可以随意传入值或指针需要
关于最后一点首先在utils中定义两个接收者不同的方法
// 方法接收者为值类型
func (p Person) PValue() {fmt.Println(Hello, my name is, p.Name)
}// 方法接收者为指针类型
func (p *Person) PPointer() {fmt.Println(Hello, my name is, p.Name)
}然后在main文件中调用
// 函数必须传入 Person 类型
func PrintPerson(p utils.Person) {fmt.Println(Persons name:, p.Name)
}func main() {// 创建值类型和指针类型的实例p1 : utils.Person{Name: 李华}p2 : utils.Person{Name: 张三}p1.PPointer() // 调用接收者为指针的方法传入值类型PrintPerson(p1) // 调用函数传入值类型p2.PValue() // 调用接收者为值类型的方法传入指针PrintPerson(*p2) // 调用函数传入解引用的指针
}程序输出如下
Hello, my name is 李华
Persons name: 李华
Hello, my name is 张三
Persons name: 张三