1、匿名组合(继承思想)
(1)当匿名字段也是一个结构体的时候,这个结构体包含的字段全部被隐式的引入当前定义的结构体中
(2)当匿名字段是非结构体时,可以用 变量.类型名 操作此变量
(3)同名字段,如果能在本作用域找到此成员,就操作此成员;如果没找到,就操作继承的成员。
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
type Student struct {
Person
id int
int
}
func main() {
// 1、初始化
var s1 = Student{Person{"LiMing", 18}, 1, 2}
fmt.Println("s1 = ", s1)
// 2、指定成员初始化
s2 := Student{Person: Person{name: "LiMing"}}
fmt.Println("s2 = ", s2)
// 3、使用匿名字段
fmt.Println("结构体匿名字段:", s1.Person)
fmt.Println("结构体匿名字段2:", s1.name)
fmt.Println("非结构体匿名字段:", s1.int)
}
2、方法(封装思想)
2.1、通过 func (参数名 类型名称) 方法名(){},给某个类型绑定一个方法,func后边的参数也会传入方法中
package main
import (
"fmt"
)
// 1、面向过程
func Add1(a, b int) int {
return a + b
}
// 2.1、面向对象,定义一个结构体MyMath
// 2.2、给MyMath绑定一个方法Add2
type MyMath struct{}
func (this MyMath) Add2(a, b int) int {
return a + b
}
func main() {
fmt.Println("Add1 = ", Add1(1, 2))
myMath := MyMath{}
fmt.Println("myMath.Add2() = ", myMath.Add2(1, 2))
}
2.2、值语义,引用语义
(1)值语义:里边的值相当于外部的拷贝,对它修改不会影响外部的值
(2)引用语义:引用传递
(3)真正使用时,调用不受方法集约束,编译器总是查找全部方法,并自动转换
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
// 值语义,里边的this相当于外部的拷贝,对他修改不会影响外部的值
func (this Person) setInfo01(name string, age int) {
this.name = name
this.age = age
}
// 引用语义,引用传递
func (this *Person) setInfo02(name string, age int) {
this.name = name
this.age = age
}
func main() {
person := Person{"LiMing", 1}
fmt.Println("person = ", person)
person.setInfo01("LiMing", 18)
fmt.Println("值语义 person = ", person)
(&person).setInfo02("Liming", 18)
fmt.Println("引用语义 person = ", person)
// 编译器内部自动做转换
person.setInfo02("LiMing", 20)
fmt.Println("引用语义2 person = ", person)
}
2.3、方法的继承
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
func (this *Person) PrintInfo() {
fmt.Println("person = ", this)
}
type Student struct {
Person
id int
}
func main() {
student := Student{Person{"LiMing", 18}, 1}
student.PrintInfo()
}
// 打印内容
person = &{LiMing 18}
2.4、方法的重写/同名方法
就近原则
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
func (this *Person) PrintInfo() {
fmt.Println("person = ", this)
}
type Student struct {
Person
id int
}
func (this *Student) PrintInfo() {
fmt.Println("student = ", this)
}
func main() {
student := Student{Person{"LiMing", 18}, 1}
student.PrintInfo()
}
// 打印内容
student = &{{LiMing 18} 1}
2.5、方法值、方法表达式
(1)方法值省略了调用者
(2)方法表达式需要把调用者写到()中
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
func (this *Person) PrintInfo() {
fmt.Println("person = ", this)
}
func main() {
person := Person{"LiMing", 18}
// 方法值
fun1 := person.PrintInfo
fun1()
// 方法表达式
fun2 := (*Person).PrintInfo
fun2(&person)
}
3、接口(多态思想)
(1)通过 type 名称 interface 定义接口,接口通常以er结尾
(2)接口中的方法只有声明,没有实现
(3)接口可以继承
package main
import (
"fmt"
)
type Personer interface {
hello()
}
type Chinese struct {
addr string
}
func (p *Chinese) hello() {
fmt.Println("你好")
}
type American struct {
addr string
}
func (p *American) hello() {
fmt.Println("hello")
}
func sayHello(p Personer) {
p.hello()
}
func main() {
sayHello(&Chinese{})
sayHello(&American{})
}
3.1、空接口不包含任何方法,即所有类型都实现了它,万能类型
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
func main() {
// 空接口没有方法,即所有类型都实现了它
s := make([]interface{}, 3)
s[0] = 1
s[1] = "hello"
s[2] = Person{}
// 类型查询
for index, value := range s {
if data, ok := value.(int); ok {
fmt.Printf("我是int类型 index = %d,data = %d\n", index, data)
} else if data, ok := value.(string); ok {
fmt.Printf("我是string类型 index = %d,data = %s\n", index, data)
} else if data, ok := value.(Person); ok {
fmt.Printf("我是Person类型 index = %d,data = %v\n", index, data)
}
}
fmt.Println("------------------------------")
// 类型查询
for index, value := range s {
switch value.(type) {
case int:
fmt.Printf("我是int类型 index = %d,data = %d\n", index, value)
case string:
fmt.Printf("我是string类型 index = %d,data = %s\n", index, value)
case Person:
fmt.Printf("我是Person类型 index = %d,data = %v\n", index, value)
}
}
}