方法
1.方法的定义
go语言中定义方法,首先需要定义结构体struct,然后就可以为结构题愉快的定义方法了。
package main
import (
"fmt"
)
type People struct{
age int
name string
}
// People的sayName方法
func (people People) sayName(){
fmt.Println(people.name)
}
func main() {
man := People{18, "kinlonli"}
woman := People{20, "zhangshan"}
man.sayName()
woman.sayName()
}
2.方法和函数的区别与联系
其实方法就是函数,他们都是为了定义一组操作的封装体。不过方法的是面向对象的,它与结构直接关联,可以直接通过结构体(java中的对象)直接调用,以 结构体.方法名 进行调用,具更高的封装性。
3.指针接收者(指针方法)
指针接收者在调用方法时候,调用前后是使用同一份内存的数据的,不会进行拷贝操作。因此频繁调用某个方法时,可以考虑使用指针,可以提升效率。
package main
import (
"fmt"
)
type People struct{
age int
name string
}
// 只需要将People类型 -> *People类型
func (people *People) change(){
people.age = 30
people.name = "zhangsan"
}
func main() {
man := People{18, "kinlonli"}
fmt.Println(man)
man.change()
fmt.Println(man)
}
[Running] go run "/Users/lijinlong/local/go/GoProjects/go_demo/main.go"
{18 kinlonli}
{30 zhangsan}
调用change函数之后,man的数据被修改了。函数传递参数时,没有对people具体内容进行拷贝,拷贝的仅仅是指针变量,因此函数体操作会对people内容进行修改。
可以尝试将*People -> People,会发现前后数据没有改变。
4.方法与指针的重定向
方法中允许指针和值之间相互转化,会隐式的将指针自动转为值,或者将值转为指针。
指针转为值
package main
import (
"fmt"
)
type People struct{
age int
name string
}
func (people People) sayName(){
fmt.Println(people.name)
}
func main() {
man := People{18, "kinlonli"}
man.sayName()
p := &man
// 会自动将p.sayName() -> (*p).sayName()
p.sayName()
}
值转为指针
package main
import (
"fmt"
)
type People struct{
age int
name string
}
func (people *People) sayName(){
fmt.Println(people.name)
}
func main() {
man := People{18, "kinlonli"}
// 会自动将man.sayName() -> (&man).sayName()
man.sayName()
p := &man
p.sayName()
}
在方法中允许这样隐式的转换,但是函数可不允许这样的转换,在函数中依旧要严格按照参数类型匹配传递参数,否则会变异不通过。
参考:
方法与指针重定向
方法与指针重定向(续)
接口
1.接口的定义
接口是一组方法签名的定义,接口变量可以保存实现了该接口方法一系列的值。
例如:
type Things inteface {
sayName()
getAge() int8
}
2. 接口的使用
接口值可以为任一实现了接口的结构体,不同类型的结构体调用相同的接口方法时展现出不同的行为,体现了多态性。比如以下代码中,Student和Teacher都实现了People这个接口,接口People可以为Student或Teacher类型的值或者对应的指针,他们调用sayName()方法时表现出了不一样的行为。
package main
import (
"fmt"
)
type People interface {
sayName()
getAge() int8
}
type Student struct{
name string
age int8
}
// Student结构体实现People接口内的方法
func (student *Student) sayName() {
fmt.Println("my name is " + student.name)
}
func (student *Student) getAge() int8{
return student.age
}
type Teacher struct {
name string
age int8
subject string
}
// Teacher结构体实现People接口内的方法
func (teacher *Teacher) sayName(){
fmt.Println("I'm " + teacher.subject + " teacher " + teacher.name)
}
func (teacher *Teacher) getAge() int8{
return teacher.age
}
func main() {
// 接口变量接受学生指针
var people1 People = &Student{name : "kinlonli", age : 18}
// 使用接口调用学生对应的方法
people1.sayName()
fmt.Println(people1.getAge())
// 接口变量接收老师的指针
var people2 People = &Teacher{name : "xiaoyue", age : 28, subject : "math"}
// 使用接口调用老师对应的方法
people2.sayName()
fmt.Println(people2.getAge())
}
[Running] go run "/Users/lijinlong/local/go/GoProjects/go_demo/main.go"
my name is kinlonli
18
I'm math teacher xiaoyue
28
3.接口的特点
- 实现是隐性的
- 接口即是值
- 空接口
第一,在go语言中接口的实现不需要像java一样显示的使用 implements 关键字显示的实现,解耦了接口定义
,接口定义可以出现在任何包中。
第二,接口就是明确的一个值,他也想函数一样作为函数的参数或者返回值。
第三,空接口就是 interface{} ,任何变量都可以赋值给空接口变量,因为任何变量都至少实现了0个方法