失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Golang 基础知识(十一.struct结构体)

Golang 基础知识(十一.struct结构体)

时间:2021-02-19 06:01:34

相关推荐

Golang 基础知识(十一.struct结构体)

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来实现面向对象。

注意:

类型名:标识自定义结构体的名称,在同一个包内不能重复。字段名:表示结构体字段名。结构体中的字段名必须唯一。字段类型:表示结构体字段的具体类型。

使用typestruct关键字来定义结构体,具体代码格式如下:

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 (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {函数体}

其中,

接收者变量:接收者中的参数变量名在命名时,官方建议使用接收者类型名称首字母的小写,而不是selfthis之类的命名。例如,Person类型的接收者变量应该命名为pConnector类型的接收者变量应该命名为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结构体)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。