🔥 个人主页:星云爱编程
🔥 所属专栏:Golang
🌷追光的人,终会万丈光芒
🎉欢迎大家点赞👍评论📝收藏⭐文章
前言:Go语言面向对象编程说明
- Golang也支持面向对象编程(OOP),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言。所以说Golang支持面向对象编程特性是比较准确的。
- Golang 没有类(class),Go语言的结构体(struct)和其它编程语言的类(class)有同等的地位,你可以理解 Golang 是基于 struct 来实现 OOP 特性的。
- Golang 面向对象编程非常简洁,去掉了传统 OOP 语言的继承、方法重载、构造函数和析构函数、隐藏的 this 指针等等。
- Golang仍然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其它OOP语言不一样,比如继承:Golang没有extends关键子,继承是通过匿名字段来实现。
- Golang面向对象(0OP)很优雅,OOP本身就是语言类型系统(type system)的一部分,通过接口(interface)关联,藕合性低,也非常灵活,在Golang中面向接口编程是非常重要的特性。
1、结构体
1.1基本介绍
- 结构体是自定义的数据类型,代表一类事物;
- 结构体变量(实例)是具体的、实际的,代表一类事物
1.2结构体声明
基本语法:
type 结构体名称 struct {
字段1 类型1
字段2 类型2
...
}
1.3字段/属性
1.3.1介绍
- 结构体字段=属性=field
- 字段是结构体的一个组成部分,一般是基本数据类型、数组,也可以是引用类型
1.3.2注意事项和使用细节
- 字段声明语法同变量,示例:字段名 字段类型
- 字段的类型可以为:基本类型、数组或引用类型
- 在创建一个结构体变量后,如果没有给字段赋值,都对应一个零值(默认值),规则同前面讲的一样:布尔类型是 false,数值是0,字符串是""。数组类型的默认值和它的元素类型相关,比如 score [3]int 则为[0,0, 0]指针,slice,和map的零值都是 nil,即还没有分配空间。
- 不同结构体变量的字段是独立,互不影响,一个结构体变量字段的更改,不影响另外一个。
1.4创建结构体变量和使用结构体字段
方式一:直接声明
var stu1 Stu
stu1.name="jack"
stu1.age=19
方式二:{}
stu2:=Stu{"tom",18}
方式三:&
var stu3 *Stu=new(Stu)
stu3.name="kk"
stu3.age=54
方式四:
var stu4 *Stu=&Stu{}
stu4.name="xx"
stu4.age=22
//方式四也可以直接赋值
var stu5 *Stu=&Stu{"bob",43}
说明:
- 方式三和方式四返回的是结构体指针
- 结构体指针访问字段的标准方式是:(*结构体指针).字段名,例如:
(*stu3).age=21
- Go对结构体指针的使用做了个简化,也支持结构体.字段名,例如方式三中的使用;Go编译器底层对stu3.age做了转化:(*stu3).age
1.5创建结构体变量时指定字段值
Go在创建结构体实例(变量)时,可以直接指定字段的值。有以下几种方式
方式一:创建变量时直接赋值
package main
import (
"fmt"
)
type Stu struct{
Name string
Age int
}
func main(){
//方式一:在创建变量时直接赋值
var stu1 Stu=Stu{"jack",15}
//简写
stu2:=Stu{"tom",13}
//在创建结构体变量时,把字段名和字段值写在一起,这种写法,就不依赖字段的定义顺序
var stu3 Stu=Stu{
Name:"张飞",
Age:43,
}
var stu4 Stu=Stu{
Age:23,
Name:"李白",
}
//简写
stu5:=Stu{
Age:98,
Name:"王林",
}
fmt.Println(stu1)
fmt.Println(stu2)
fmt.Println(stu3)
fmt.Println(stu4)
fmt.Println(stu5)
}
方式二:返回结构体的指针类型
package main
import (
"fmt"
)
type Stu struct{
Name string
Age int
}
func main(){
//方式二:返回结构体的指针类型
var stu1 *Stu=&Stu{"高启强",33}
//简写
stu2:=&Stu{"祁同伟",44}
//在创建结构体指针变量时,把字段名和字段值写在一起,这种写法,就不依赖字段的定义顺序
var stu3 *Stu= &Stu{
Age:21,
Name:"李达康",
}
//简写
stu4:=&Stu{
Name:"沙瑞金",
Age:43,
}
fmt.Println(*stu1)
fmt.Println(*stu2)
fmt.Println(stu3)
fmt.Println(stu4)
}
1.6结构体内存分配机制
在 Go 语言中, 结构体(struct) 的内存分配机制遵循以下规则:
1.连续内存分配
结构体的字段在内存中是连续分配的。每个字段按照定义的顺序依次存储在内存中。
type Point struct {
X int
Y int
}
内存布局
| X (int) | Y (int) |
2.内存对齐
Go 语言会根据字段的类型进行内存对齐,以提高访问效率。
对齐规则如下:
- 字段的起始地址必须是其类型大小的整数倍。
- 结构体的总大小必须是其最大字段大小的整数倍
type Example struct {
A int8 // 1 字节
B int32 // 4 字节
C int64 // 8 字节
}
内存布局:
| A (1) | padding (3) | B (4) | C (8) |
总大小为 16 字节(1 + 3 + 4 + 8)
3.空结构体
空结构体( struct{} )不占用内存空间,大小为 0。
type Empty struct{}
fmt.Println(unsafe.Sizeof(Empty{})) // 输出 0
4.嵌套结构体
嵌套结构体的内存分配规则与普通结构体相同,字段按顺序连续存储。
type Inner struct {
A int
B int
}
type Outer struct {
X int
Y Inner
}
内存布局:
| X (int) | Y.A (int) | Y.B (int) |
5.指针字段
指针字段占用固定大小(64 位系统为 8 字节,32 位系统为 4 字节),指向实际数据的内存地址。
type PointerExample struct {
P *int
}
内存布局:
| P (8 字节) |
6.内存分配优化
Go 编译器会对结构体的内存布局进行优化,以减少内存浪费。例如,将较小的字段放在一起,减少填充字节。
ty