1、继承
package main

import "fmt"
//定义一个Person类
type Person struct {
    id int
    name string
    age int
}
//分别定义Student与Teacher类,继承Person
type Student struct {
    //匿名字段:只有类型,没有成员的名字
    Person
    score float64
}
type Teacher struct {
    Person
    salary float64
}

func main()  {
    var stu Student = Student{Person{101,"小松",20},23.5}
    var tea Teacher = Teacher{Person{10001,"小红",35},15000}
    fmt.Println(stu)
    fmt.Println(tea)
}

执行结果:
{{101 小松 20} 23.5}
{{10001 小红 35} 15000}    
2、部分初始化
func main()  {
    //全部参数都进行初始化
    var stu Student = Student{Person{101,"小松",20},23.5}
    var tea Teacher = Teacher{Person{10001,"小红",35},15000}
    //部分参数进行初始化
    var stu1 Student = Student{score: 100}
    //只将父类中的参数进行初始化,且只对id进行初始化,这里需要注意初始化的方式
    var stu2 Student = Student{Person:Person{id:1001}}
    fmt.Println(stu1)
    fmt.Println(stu2)
    fmt.Println(stu)
    fmt.Println(tea)
}
执行结果:
//由于id是与age为int类型,所以默认初始化为0,name由于是string类型,所以默认初始化为null
{{0  0} 100}
{{1001  0} 0}
{{101 小松 20} 23.5}
{{10001 小红 35} 15000}
3、获取对象中成员变量
func main()  {
    var stu1 Student = Student{Person{101,"小松",20},95}
    var stu2 Student = Student{Person{10001,"小红",35},100}

    fmt.Println(stu1.id)
    fmt.Println(stu2.Person.id)
}
执行结果:
//先去Student对像中查找id,当Student对象中没有,回去父类对象中查找
101
10001
4、成员变量的修改
func main()  {
    var stu1 Student = Student{Person{101,"小松",20},95}
    var stu2 Student = Student{Person{10001,"小红",35},100}
    //如果是调用其他函数老进行修改stu中的成员变量则需要使用到指针
    var p *Student
    p = &stu1
    updateInfo(p)
    //如果需要在本函数中进行修改
    stu2.score = 60
    fmt.Println(stu1.score)
    fmt.Println(stu2.score)
}

func updateInfo(stu *Student)  {
    stu.score = 100
}

执行结果
100
60
5、指针类型匿名对象初始化
import "fmt"

type Person struct {
    id int
    name string
    age int
}

type Student struct {
    //匿名字段:只有类型,没有成员的名字
    *Person
    score float64
}

func main()  {
    //需要注意指针类型匿名对象初始化与匿名对象初始化的区别,指针类型匿名对象初始化需要在匿名对象前加上&符号,用以获取对象的地址
    var stu1 Student = Student{&Person{101,"小松",20},95}
    var stu2 Student = Student{&Person{10001,"小红",35},100}
    
    fmt.Println(stu1)
    fmt.Println(stu2)
    fmt.Println(stu2.name)
}

执行结果:
//因为Student对象是一个指针变量,所以打印的是一个地址,这个地址指向的是Person类初始化的内存地址
//如果需要打印初始化的内容,需要使用stu2.name的方式
{0xc00005a3c0 95}
{0xc00005a3e0 100}
小红
6、多重继承以及初始化
import "fmt"

type Object struct {
    id int
}
type Person struct {
    Object
    name string
    age int
}

type Student struct {
    //匿名字段:只有类型,没有成员的名字
    *Person
    score float64
}

func main()  {
    //需要注意指针类型匿名对象初始化与匿名对象初始化的区别,指针类型匿名对象初始化需要在匿名对象前加上&符号,用以获取对象的地址
    var stu1 Student = Student{&Person{Object{10011},"小松",20},95}
    var stu2 Student = Student{&Person{Object{10012},"小红",35},100}

    fmt.Println(stu1)
    fmt.Println(stu2)
    fmt.Println(stu2.id)
}

执行结果:
{0xc00005a3c0 95}
{0xc00005a3e0 100}
1001
7、给结构体添加方法
import "fmt"

type Student struct {
    id int
    name string
    age int
}
//给结构体添加方法
func (stu Student)showPrint()  {
    fmt.Println(stu)
}

func main()  {
    stu := Student{10086,"小松",34}
    //由于已经给结构体添加方法因此,这里可以直接调用func函数(方法)
    //完成对象方法的调用,并将对象的值传递给方法
    stu.showPrint()
}

打印结果:
{10086 小松 34}
8、利用结构体方法修改初始化值
import "fmt"

type Student struct {
    id int
    name string
    age int
}

func (stu Student)showPrint()  {
    fmt.Println(stu)
}

func (stu *Student)EditInfo()  {
    stu.name = "小明"
}

func main()  {
    stu := Student{10086,"小松",34}
    //想要利用结构体方法去修改初始化参数值,需要引入指针
    stu.EditInfo()
    stu.showPrint()
}

执行结果:
{10086 小明 34}

 9、方法的继承

import "fmt"

type Person struct {
    name string
    age int
    sex string
}

type Teacher struct {
    Person
    school string
}

func (p *Person)showPerson()  {
    fmt.Println(p)
}

func main()  {
    mathTeacher := Teacher{Person{"小明",34,""},"北京大学"}
    mathTeacher.showPerson()
}

执行结果:
&{小明 34 女}
10、方法重写
import "fmt"
//定义一个父类
type Person struct {
    name string
    age int
    sex string
}

type Teacher struct {
    Person
    school string
    score float64
}

//给父类添加一个方法
func (p *Person)printInfo(){
    fmt.Println("这是父类中的方法")
}

func (t *Teacher)printInfo()  {
    fmt.Println("这是子类中的方法")
}

func (p *Person)showPerson()  {
    fmt.Println(p)
}

func main()  {
    var tea Teacher
    tea.printInfo()
    tea.Person.printInfo() //通过调用该方式调用父类中的方法
}

//如果父类中的方法名称与子类中的方法名称相同,通过子类的对象调用的是子类中的方法
执行结果:
这是子类中的方法
11、方法值与方法表达式
import "fmt"

type Person struct {
    name string
    age int
    sex string
}

//给父类添加一个方法
func (p *Person)printInfo(){
    fmt.Println("这是父类中的方法")
}

func main()  {
    per := Person{"小明",16,""}
    //f为方法类型的数据
    //f := per.printInfo
    //fmt.Printf("%T\n",f)
    //f()
    //方法表达式
    f := (*Person).printInfo
    f(&per)
}