结构实例化


:=自动推导实例化方式

  1. book1:= Books{value1, value2...valuen}
  2. book2:= Books{ key1: value1, key2: value2..., keyn: valuen}

例子:

  1. book1:=Books{1,"Go语言入门教程","deer","Go语言"}
  2. book2:=Books{id: 2,title: "Go语言进阶教程",author: "deer",subject: "Go语言"}
  1. package main
  2. import "fmt"
  3. type Books struct {
  4. id int
  5. title string
  6. author string
  7. subject string
  8. }
  9. func main() {
  10. //key -> value创建结构体变量
  11. book2 := Books{
  12. id: 2,
  13. title: "Go语言进阶",
  14. author: "yu",
  15. subject: "描述",
  16. }
  17. //简洁创建结构体变量
  18. book3 := Books{3,"Go语言深入","yu","描述"}
  19. fmt.Printf("book2=%v\n",book2)
  20. fmt.Printf("book2.title=%s\n",book2.title)
  21. fmt.Printf("book3=%v\n",book3)
  22. fmt.Printf("book3.title=%s\n",book3.title)
  23. }
  24. /*输出结果*/
  25. book2={2 Go语言进阶 yu 描述}
  26. book2.title=Go语言进阶
  27. book3={3 Go语言深入 yu 描述}
  28. book3.title=Go语言深入

指针类型实例化方式

  1. var struct_pointer *Books
  1. package main
  2. import "fmt"
  3. type Books struct {
  4. id int
  5. title string
  6. author string
  7. subject string
  8. }
  9. func main() {
  10. var book4 *Books
  11. book4 = new(Books)
  12. (*book4).id=4
  13. (*book4).title="Go语言放弃"
  14. //底层book4->(*book4)
  15. book4.author="yu"
  16. book4.subject="描述"
  17. fmt.Println(book4)
  18. }
  19. &{4 Go语言放弃 yu 描述}

二、结构体使用

自定义类型

Go语言允许我们自定义类型,自定义类型有2种方式。

语法
自定义类型是定义了一个全新的数据类型,Go使用type关键字创建一个新的数据类型

  1. type newtype oldtype

实例

  1. package main
  2. import "fmt"
  3. //integer和int都是int类型,integer派生自int,但是在Go语言当中被认为是不同的数据类型。
  4. type integer int
  5. func main() {
  6. var intvariable int
  7. var integervariable integer
  8. /*
  9. integer和int是不同的数据无法相互赋值
  10. cannot use integervariable (type integer) as type int in assignment
  11. */
  12. intvariable=int(integervariable)//强制类型转换
  13. fmt.Println(intvariable,integervariable)
  14. }

上面例子中我们使用type关键字从int类型中派生了一个新的类型。不同的数据类型无法相互赋值,只能通过强制类型转换。

结构体定义

go语言使用struct定义一个自定义类型,当用户声明一个新的类型,告诉编译器申请多大内存

语法**
在Go语言中 将类型放在后面

  1. type structName struct{
  2. field fieldtype
  3. field fieldtype
  4. field fieldtype
  5. }

实例

  1. type UsersInfo struct {
  2. //字段可以是任何类型,函数接口都可以
  3. name string //可以说成属性,但是比较粗糙
  4. age int
  5. sex string
  6. hobby []string
  7. moreinfo map[string]interface{}
  8. }

结构体实例化

  1. //结构体名首字母小写表示私有,大写表示公有
  2. type UsersInfo struct {
  3. //字段可以是任何类型,函数接口都可以
  4. name string //可以说成属性,但是比较粗糙
  5. age int
  6. sex string
  7. hobby []string
  8. moreinfo map[string]interface{}
  9. }
  10. func main() {
  11. //基于结构体类型,创建一个变量
  12. var boby UsersInfo //boby是UsersInfo类型
  13. boby.name="deer"
  14. boby.age=18
  15. boby.sex="男"
  16. boby.hobby=[]string{"编程","运动"}
  17. boby.moreinfo= map[string]interface{}{
  18. "city":"杭州",
  19. "language":"english",
  20. }
  21. fmt.Printf("boby的name=%s,boby的hobby=%v\n",boby.name,boby.hobby)
  22. }

简短方式初始化结构体变量

  1. //:=简短声明定义一个结构体变量
  2. huge :=UsersInfo{
  3. name: "胡歌",
  4. age: 35,
  5. sex: "男",
  6. hobby: []string{"拍电影","公益"},
  7. moreinfo: map[string]interface{}{
  8. "role":"演员",
  9. },
  10. }
  11. lige :=UsersInfo{"55"}
  12. fmt.Printf("hu=%v",huge)

指针类型结构体实例化

  1. ins := new(T) //new(T)开辟指定类型的变量并赋初值,并返回该变量的内存地址

结构体内存布局

image.png
image.png

任意类型添加方法

在Go语言中,接收者的类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。 举个例子,我们基于内置的int类型使用type关键字可以定义新的自定义类型,然后为我们的自定义类型添加方法。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. //使用type 将int定义为自定义的integer类型
  6. type integer int
  7. //为自定义integer类型添加Say方法
  8. func (this integer)Say( ) {
  9. fmt.Println("Hello, 我是一个int。")
  10. }
  11. func main( ) {
  12. var m1 integer
  13. m1= 100
  14. m1.Say()
  15. fmt.Printf("%#v %T\n", m1, m1) //100 main.integer
  16. }

嵌套结构体(继承和多继承)

Go语言虽然没有继承,但是我们可以使用嵌套结构体达到类似继承的效果。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. //父类
  6. type Human struct {
  7. Name string
  8. Age int
  9. Sex string
  10. }
  11. //学生子类
  12. type Student struct {
  13. StudentId int
  14. Human
  15. }
  16. func main( ) {
  17. student1:=Student{
  18. StudentId: 1,
  19. Human:Human{
  20. Name: "小红",
  21. Age: 15,
  22. Sex: "女",
  23. },
  24. }
  25. fmt.Println(student1.Name)//Go语言语法糖 底层->student1.Human.Name
  26. }

匿名字段

定义结构体时,成员字段可以只有类型,而没有字段名,这样的字段称为匿名字段。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. //父类
  6. type Human struct {
  7. Name string
  8. Age int
  9. Sex string
  10. }
  11. //学生子类
  12. type Student struct {
  13. StudentId int
  14. string //匿名字段
  15. Human //匿名结构体
  16. //Human (Duplicate field 'Human')
  17. }
  18. func main( ) {
  19. Student1:=Student{
  20. StudentId: 1,
  21. string: "作业",
  22. Human: Human{
  23. Name: "小红",
  24. Age: 15,
  25. Sex: "女",
  26. },
  27. }
  28. fmt.Println(Student1)
  29. {1 作业 {小红 15 女}}

一、Go结构体概念

Go语言支持面向对象编程(OOP)。但是和传统的面向对象编程有区别,并不是纯粹的面向对象编程语言。

Go语言没有其他编程语言中的类(class),但是可以使用结构体(struct)来实现面向对象特性。

image.png
提取属性,形成新的数据类型(结构),通过这种数据类型创建多个变量

  • 结构体是自定义的数据类型,描述一类事物(猫)
  • 结构体变量(实例)是具体的,实际的,代表一个具体事物

  • 二、Go结构体使用

1. 定义结构体

结构体定义使用type关键字开头,结构体名,后置结构类型struct关键字,结构体中有一个或多个成员字段。
语法:

  1. type 结构体名 struct {
  2. field field_type
  3. field field_type
  4. field field_type
  5. }

结构体成员也可以称为属性和“字段”,这些字段有以下特性:

  • 字段拥有自己的类型和值;
  • 字段名必须唯一;
  • 字段的类型基本数据类型,引用类型甚至另一个结构体。

image.png
image.png

结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存
例子:

  1. type Books struct {
  2. id int
  3. title string
  4. author string
  5. subject string
  6. }


2.结构体变量(结构体实例化)

结构体本身也是一种数据类型,可以像基本数据类型一样,用来声明一个结构体类型的变量。

基本声明方式

  1. package main
  2. import "fmt"
  3. type Books struct {
  4. Id int
  5. Title string
  6. Author string
  7. Subject string
  8. }
  9. func main() {
  10. var book1 Books //book1是Books类型的变量
  11. book1.Id=1
  12. book1.Title ="Go语言"
  13. book1.Author="cdeer"
  14. book1.Subject="Go语言进阶"
  15. fmt.Println(book1) //{1 Go语言 cdeer Go语言进阶}
  16. }

编译器推导类型声明方式

  1. package main
  2. import "fmt"
  3. type Books struct {
  4. Id int
  5. Title string
  6. Author string
  7. Subject string
  8. }
  9. func main() {
  10. book2 := Books{1, "Go语言", "cdeer", "Go语言进阶"}
  11. fmt.Println(book2) //{1 Go语言 cdeer Go语言进阶}
  12. }

指针类型声明方式

3.结构体变量内存布局

4.结构体方法

Go语言中的方法和传统编程语言的方法不太一样,方法和类并非组织在一起,传统的oop类和方法放在一个文件,而Go只要在同一个包里就可,可分散在不同文件里。go的理念就是数据和实现分离,引用官方说法:
“Methods are not mixed with the data definition (the structs): they are orthogonal to types; representation(data) and behavior (methods) are independent”

Go语言中的方法(Mehod)是一种作用于特定类型上(方法和指定的数据类型绑定),因此自定义类型都可以有方法,不仅仅是结构体。

5.结构体工厂模式

与传统面向对象编程语言不同,Go语言的结构体没有构造函数,通常使用工厂模式来解决这个问题。

  1. package model
  2. type students struct {
  3. stuid int
  4. name string
  5. sex string
  6. class string
  7. }
  8. //工厂模式
  9. func NewStudent(stuid int,name,sex,class string) *students { ///返回*students类型
  10. return &students{stuid: stuid,name: name,sex: sex,class: class}//结构体实例化并返回地址
  11. }


  1. package main
  2. import (
  3. "fmt"
  4. "gotest1/src/model"
  5. )
  6. type Books struct {
  7. Id int
  8. Title string
  9. Author string
  10. Subject string
  11. }
  12. func main() {
  13. xiaohong:=model.NewStudent(1,"小红","女","1班")
  14. fmt.Println(xiaohong)//&{1 小红 女 1班}
  15. }

三、Go面向对象

Go语言仍然支持面向对象三大特性。Go语言实现方式与传统面向对象编程语言不同。

1.封装

Go语言的封装和传统编程语言不同。Go语言使用首字母大小写方式代表公有私有权限,大写表示包外可访问,小写表示包外不能访问。

image.png
image.png

2.继承和多继承

与C++/Java等面向对象编程语言不同,Go语言没有显式的继承,而是通过结构体嵌套另一个匿名结构实现继承。

  1. package mypackage
  2. import "fmt"
  3. //父类
  4. type person struct {
  5. Name string
  6. Sex string
  7. Age int
  8. }
  9. //子类
  10. type Student struct {
  11. person //匿名结构实现继承
  12. StudentId int
  13. }
  14. type Teacher struct {
  15. person
  16. TeacherId int
  17. }
  18. //工厂函数
  19. func NewStudent(name,sex string,age,stuid int) *Student {
  20. return &Student{person{Name: name,Sex: sex,Age: age} ,stuid}
  21. }
  22. //父类方法Eat()
  23. func (this *person)Eat() {
  24. fmt.Println(this.Name+"正在吃饭parent")
  25. }
  26. //子类方法 重载父类Eat()
  27. func (this *Student)Eat() {
  28. fmt.Println(this.Name+"正在吃饭child")
  29. }
  30. func main() {
  31. stu:=mypackage.NewStudent("多多","女",15,1)
  32. //子类拥有父类的属性和方法
  33. fmt.Println(stu.Name)//多多
  34. stu.Eat()//多多正在吃饭parent
  35. //子类的属性和重载父类方法
  36. fmt.Println(stu.StudentId)//1
  37. stu.Eat()//多多正在吃饭child
  38. }

3.0多态

在Go语言中使用接口来实现多态特征。