struct结构体
1.定义2.匿名结构体3.键值对初始化4.构造函数4.1 (值)方法和接收者4.2 (指针)方法和接受者4.3 结构体的“继承4.4 序列化与反序列化4.5总结(知识点综合使用案例:学生信息管理)注意:根据内存对齐原则,结构体里面的数据类型,应根据类型所占的大小,依次排序,从小到大,越小越小前,主要是优化内存读取速度。(取值是有一个”框“的(32 :4,64,:8),根据框取值时候是一块一块的取,超出框的部分,取两次,并删除多余的部分再和前面取得数据合并,操作变多了,消耗就多)
type Part1 struct {a boolb int32c int8d int64e byte}type Part2 struct {e bytec int8a boolb int32d int64}func main() {part1 := Part1{}part2 := Part2{}fmt.Printf("part1 size: %d, align: %d\n", unsafe.Sizeof(part1), unsafe.Alignof(part1))fmt.Printf("part2 size: %d, align: %d\n", unsafe.Sizeof(part2), unsafe.Alignof(part2))}
输出结果:
part1 size: 32, align: 8part2 size: 16, align: 8
1.定义
Go语言中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,Go语言提供了一种自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体,英文名称struct
。 也就是我们可以通过struct
来定义自己的类型了。
Go语言中通过struct
来实现面向对象。
注意:
类型名:标识自定义结构体的名称,在同一个包内不能重复。字段名:表示结构体字段名。结构体中的字段名必须唯一。字段类型:表示结构体字段的具体类型。
使用type
和struct
关键字来定义结构体,具体代码格式如下:
type 类型名 struct {字段名 字段类型字段名 字段类型…}
举个例子:
type person struct {name stringcity stringage int8}func main() {var p1 personp1.name = "张三"p1.city = "北京"p1.age = 18fmt.Printf("p1=%v\n", p1) //p1={张三 北京 18}fmt.Printf("p1=%#v\n", p1) //p1=main.person{name:"张三", city:"北京", age:18}}
2.匿名结构体
注意:一般用于零时场景
var res struct{
name string
age int
}
res.name = “李四”
res.age = 19
fmt.Println(res)
3.键值对初始化
方式一:使用&
对结构体进行取地址操作相当于对该结构体类型进行了一次new
实例化操作
p3 := &person{}fmt.Printf("%T\n", p3)//*main.personfmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"", city:"", age:0}p3.name = "七米"p3.age = 30p3.city = "成都"fmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"七米", city:"成都", age:30}
方式二:
p5 := person{name: "小王子",city: "北京",age: 18,}
方式三:对结构体指针进行键值对初始化
p6 := &person{name: "小王子",city: "北京",age: 18,}
方式四:
p8 := &person{"沙河娜扎","北京",28,}fmt.Printf("p8=%#v\n", p8) //p8=&main.person{name:"沙河娜扎", city:"北京", age:28}
使用这种格式初始化时,需要注意:
必须初始化结构体的所有字段。初始值的填充顺序必须与字段在结构体中的声明顺序一致。该方式不能和键值初始化方式混用。
4.构造函数
作用:不用每次都初始化
注意:
构造函数都是以new开头的;
返回数据主要分结构体和结构体指针;
字段或者数据小的时候用结构体;
结构体比较打得时候用结构体指针,减少内存开销
返回结构体:
type persion struct {
name string
age int
}
func newP1 (x string ,y int) persion{
return persion{
name : x,
age : y,
}
}
func main(){
p2 := newP1(“张三”,13)
fmt.Printf("%#v",p2)
fmt.Println(p2)
}
4.1 (值)方法和接收者
Go语言中的方法(Method)
是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者(Receiver)
。接收者的概念就类似于其他语言中的this
或者self
。
方法的定义格式如下:
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {函数体}
其中,
接收者变量:接收者中的参数变量名在命名时,官方建议使用接收者类型名称首字母的小写,而不是self
、this
之类的命名。例如,Person
类型的接收者变量应该命名为p
,Connector
类型的接收者变量应该命名为c
等。接收者类型:接收者类型和参数类似,可以是指针类型和非指针类型。方法名、参数列表、返回参数:具体格式与函数定义相同。
举个例子:
//Person 结构体type Person struct {name stringage int8}//NewPerson 构造函数func NewPerson(name string, age int8) *Person {return &Person{name: name,age: age,}}//Dream Person做梦的方法func (p Person) Dream() {fmt.Printf("%s的梦想是学好Go语言!\n", p.name)}func main() {p1 := NewPerson("小王子", 25)p1.Dream()}
4.2 (指针)方法和接受者
注意:
1.需要修改接收者中的值
2.接收者是拷贝代价比较大的大对象
3.保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者。
type persion struct {
name string
age int
}
func newP1(name string ,age int) persion {
return persion{
name: name,
age: age,
}
}
func ( p *****persion ) brithday(){
p.age++
fmt.Printf("%s 今年是 %d 岁了",p.name,p.age)
}
func main(){
p2 := newP1(“张三”,18)
p2.brithday()
fmt.Printf(”%s 今天 %d 岁了“,p2.name,p.age) // 张三今天19 岁了
}
4.3 结构体的“继承
注意:在一个结构体里面调用其他结构体,就可以使用其他结构体的方法
//Animal 动物type Animal struct {name string}func (a *Animal) move() {fmt.Printf("%s会动!\n", a.name)}//Dog 狗type Dog struct {Feet int8*Animal //通过嵌套匿名结构体实现继承}func (d *Dog) wang() {fmt.Printf("%s会汪汪汪~\n", d.name)}func main() {d1 := &Dog{Feet: 4,Animal: &Animal{//注意嵌套的是结构体指针name: "乐乐",},}d1.wang() //乐乐会汪汪汪~d1.move() //乐乐会动!}
4.4 序列化与反序列化
import (
“fmt”
"encoding/json"
)
type Persion struct{
Name stringjson:"name"
// N大写是外部包可以引用
Age intjosn:"age"
}
func main (){
a := Persion{
Name:“张三”,
Age:18,
}
data , err := json.Marshal(a)// 序列化
if err != nil{
fmt.Println(“this is error”)
return
}
fmt.Println(“下面是json”)
fmt.Println(string(data))
var a1 Persion
res :={"name":"张三","Age":18}
err = json.Unmarshal([]byte(res),&a1)// 反序列化,&a1 是取地址,不然只是拷贝一个空
if err != nil{
fmt.Println(“this is err122”)
}
fmt.Println(“下面是反序列化”)
fmt.Printf("%#v",a1)
}
4.5总结(知识点综合使用案例:学生信息管理)
package main
import (
“fmt”
“os”
)
/*
使用“面向对象”的思维方式编写一个学生信息管理系统。
学生有id、姓名、年龄、分数等信息
程序提供展示学生列表、添加学生、编辑学生信息、删除学生等功能
*/
// 定义学生
type student struct {
id int64
name string
}
type sMangger struct{
allStudent map[int64]student
}
// 注意:变量不能存储数据,只是定义数据类型
var smr sMangger // 申明变量存储学生管理信息
// 展示学生信息
func (m sMangger) showInfo(){
// fmt.Println(m)for _ , v := range m.allStudent{fmt.Printf("学号: %d , 姓名:%s\n", v.id , v.name)}
}
func newStudent(id int64 , name string) student {
return student{
id:id,
name:name,
}
}
// 添加学生信息
func (m sMangger) addInfo(id int64 , name string){
stu := newStudent(id,name)
m.allStudent[id] = stu
}
// 编辑
func (m sMangger) updateInfo(id int64){
data , ok := m.allStudent[id]
if !ok {
fmt.Println(“没有这个玩意儿”)
return
}
fmt.Printf(“您要修改的学生信息为:学号:%d 姓名:%s”, data.id , data.name)
fmt.Print(“请输入您要修改的姓名”)
var xinName string
fmt.Scan(&xinName)
data.name = xinName // 赋值
m.allStudent[id] = data // 更新
}
// 删除
func (m sMangger) deleteInfo(id int64){
data , ok := m.allStudent[id]
if !ok {
fmt.Println(“没有这个人哟~~”)
return
}
fmt.Printf(“学生信息为:学号;%d 姓名:%s”, data.id , data.name)
fmt.Println(“确定要删除吗? 1:确定 0:取消”)
var xinNum int64
fmt.Scan(&xinNum)
delete(m.allStudent,id)
}
func main(){
var (num int64id int64name stringisOk int64)smr = sMangger{allStudent: make(map[int64]student,100),}for {// 选择项目fmt.Print(`我们提供一下集中选项(请输入编号进行操作):1.查看学生信息;2.添加学生信息;3.编辑学生信息;4.删除学生信息;请选择:`)// 接受用户的输入的选项服务fmt.Scan(&num)// 判断执行要执行的动作switch num{case 1:fmt.Println("您选择了1 查看学生信息")smr.showInfo()case 2:fmt.Println("您选择了2 添加学生信息")fmt.Print("请输入学生学号 ")fmt.Scan(&id)fmt.Print("请输入学生姓名 ")fmt.Scan(&name)fmt.Printf("您确定这是要添加的学生信息吗?学号: %d 姓名: %s ,1:确定 0:取消 ",id,name)fmt.Scan(&isOk)if isOk == 1 {// fmt.Println("ok")// 执行逻辑// add := smr.addInfo(id,name)}else{fmt.Println("cannl")os.Exit(1)}case 3:fmt.Println("您选择了3 编辑学生信息")fmt.Print("请输入学号:")fmt.Scan(&id)smr.updateInfo(id)case 4:fmt.Println("您选择了4 删除学生信息")fmt.Print("请输入学号:")fmt.Scan(&id)smr.deleteInfo(id)default:fmt.Println("当前没有此选项服务哟")fmt.Println("很高兴为您服务")os.Exit(1)}}
}
如果觉得《Golang 基础知识(十一.struct结构体)》对你有帮助,请点赞、收藏,并留下你的观点哦!