结构体扩展允许将多个结构体组合成一个新的结构体,在新的结构体中,允许像访问自己内部成员一样访问内嵌结构体的字段和方法。

结构体扩展般形式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type Student struct {
	id   int
	name string
}

type StudentLeader struct {
	Student
	job string
}

func (s Student) Display() {
	fmt.Printf("Student id:%d,name:%s\n", s.id, s.name)
}

func (sl StudentLeader) Display() {
	fmt.Printf("Student id:%d,name:%s job %s\n", sl.id, sl.name, sl.job)
}

func main() {
	var stu = Student{1001, "张三"}
	stu.Display() //Student id:1001,name:张三
	var stuLeader = StudentLeader{Student{1002, "李四"}, "班长"}
	stuLeader.Display() //Student id:1002,name:李四 job 班长
}

通过结构体扩展,StudentLeader可以访问其内嵌的Student结构中的字段和方法,但是这两个类型本质上是不同的,而且也不是OOP中的继承关系,这一点可以看上面例子中StudentLeader 的创建过程,如果是继承关系,那么就不需要单独为内部的Student单独创建一个结构体了。

我们再给这两个类型增加一些方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
func (ps *Student) CopyFrom(fs Student) {
	ps.id = fs.id
	ps.name = fs.name
}

func (psl *StudentLeader) CopyFrom(fsl StudentLeader) {
	psl.id = fsl.id
	psl.name = fsl.name
	psl.job = fsl.job
}

func main() {
	var stu = Student{1001, "张三"}
	stu.Display() //Student id:1001,name:张三
	var stuLeader = StudentLeader{Student{1002, "李四"}, "班长"}
	stuLeader.Display() //Student id:1002,name:李四 job 班长

	var stu2 = Student{1003, "王五"}
	var stuLeader2 = StudentLeader{Student{1004, "赵六"}, "学习委员"}

	stu.CopyFrom(stu2)
	stu.Display() //Student id:1003,name:王五
	stuLeader.CopyFrom(stuLeader2)
	stuLeader.Display() //Student id:1004,name:赵六 job 学习委员

	//stu.CopyFrom(stuLeader2) //compile error:cannot use stuLeader2 (variable of type StudentLeader) as Student value in argument to stu.CopyFromcompilerIncompatibleAssign
	stu.CopyFrom(stuLeader2.Student) //ok
	stu.Display()                    //Student id:1004,name:赵六
}

当调用stu.CopyFrom(stuLeader2)时出现编译错误,从而说明StudentStudentLeader不是“Is a”的关系而是“Has a”的关系,尽管后者已经拥有了前者的所有字段和方法。

BGM