什么是method(方法)?method是函数的另外一种形态,隶属于某个类型的方法。
method的语法:
func (r Receiver) funcName (parameters) (result)
receiver可以看作是method的第一个参数,method并且支持继承和重写。
- Go中虽没有class,但依旧有method
- 通过显示说明receiver来实现与某个类型的结合
- 只能为同一个包中的类型定义方法
- receiver可以是类型的值或者指针
- 不存在方法重载
- 可以使用值或指针来调用方法,编译器会自动完成转换
- 从某种意义上来说,方法是函数的语法糖,因为receiver其实就是方法所接收的第一个参数(Method Value vs. Method Expression)
- 如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法
- 类型别名不会拥有底层类型所附带的方法
- 方法可以调用结构中的非公开字段
⽅法总是绑定对象实例,并隐式将实例作为第⼀实参 (receiver)。
• 方法有一个值类型和指针类型的接受者时,都可以直接调用,内部会
自动进行语法的转换。
package main import ( "fmt" ) type A struct { Name string } type B struct { Name string } func main() { //Receiver 可以是类型的值或者指针 a := A{} a.Print() fmt.Println(a.Name) //打印为修改后的值 b := B{} b.Print() fmt.Println(b.Name) //打印为空 } //引用类型,指针的拷贝 func (a *A) Print() { a.Name = "AA" fmt.Println("A...") } //值类型,值得拷贝 func (b B) Print() { b.Name = "BB" fmt.Println("B...") }
提阶,方法也支持提阶
emp1 := Employee{ name: "张三", salary: 6000, currency: "$", age: 18, Address: Address{"山东", "济南"}, } //提阶 emp1.fullAddress() //山东 济南,提阶相当于直接访问Address里的 emp1.Address.fullAddress() //山东 济南
非结构类型的方法
非结构体类型也可以定义方法,不过这里需要注意一点。为了定义某个类型的方法,接收者类型的定义与方法的定义必须在同一个包中。
因为必须在一个包中而int则在main包中我们没法去定义这个里为了简单直观,给int声明了别名
//非结构体方法扩展 type myInt int func (a myInt) add(b myInt) myInt { return a + b } func main() { //调用扩展的方法 num1 := myInt(5) num2 := myInt(10) sum := num1.add(num2) fmt.Println("Sum is", sum) }
package main import ( "fmt" "math" ) //Employee 需要添加注释或者改成非导出变量(首字母小写) type Employee struct { name string currency string salary int age int Address } //Address 代码规范 type Address struct { city string state string } //Rectangle 代码规范 type Rectangle struct { width float32 height float32 } //Circle 代码规范 type Circle struct { radius float32 } //Employee 的方法 func (e Employee) displaySalary() { fmt.Println(e) } func (e Employee) changeName(newName string) { e.name = newName } func (e *Employee) changeAge(newAge int) { e.age = newAge } //Address 的方法 func (add Address) fullAddress() { fmt.Println(add.city, add.state) } //Rectangle 的方法计算面积 func (r Rectangle) getArea() float32 { return r.width * r.height } //Circle 的方法 func (c Circle) getArea() float32 { return math.Pi * c.radius * c.radius } //非结构体方法扩展 type myInt int func (a myInt) add(b myInt) myInt { return a + b } func main() { //调用方法 emp1 := Employee{ name: "张三", salary: 6000, currency: "$", age: 18, Address: Address{"山东", "济南"}, } emp1.displaySalary() fmt.Println("Before call changeName ", emp1.name) //修改名字,未发生变化因为是值传递 emp1.changeName("zhangsan") fmt.Println("After call changeName ", emp1.name) //After call changeName 张三 fmt.Println("Before change age", emp1.age) //利用指针来修改年龄 emp1.changeAge(50) fmt.Println("After change age", emp1.age) //After change age 50 //提阶 emp1.fullAddress() //山东 济南,提阶相当于直接访问Address里的 emp1.Address.fullAddress() //山东 济南 //计算面积 re := Rectangle{20, 30} c := Circle{40} //两个类型调用同名方法 fmt.Println(re.getArea()) fmt.Println(c.getArea()) //调用扩展的方法 num1 := myInt(5) num2 := myInt(10) sum := num1.add(num2) fmt.Println("Sum is", sum) }