3.11 Go Struct结构体
3.11 Go Struct结构体
Golang支持OOP面向对象编程。
Go的结构体struct
如同python的class
。
Go基于struct实现OOP特性,只有组合composition
这个特性。
2. 结构体概念
1)将一类事务特性提取出一个新的数据类型,就是结构体。
2)通过结构体可以创建多个实例。
3)可以是Student结构体、可以是Animal、Person结构体。
3. 结构体特点
1)struct用于定义复杂数据结构
2)struct可以包含多个字段
3)struct可以定义方法(注意不是函数,是golang的method)
4)struct可以是值类型
5)struct类型可以嵌套
6)Go没有class,只有struct类型
7)结构体是自定义类型,不得与其他类型强转
8)可以为struct每一个字段添加tag,这个tag可以反射机制获取,场景如json序列化和反序列化。
4. 结构体定义
package main import "fmt" type Person struct {
Name string
Age int
}
func main() {
//声明方式
p1 := Person{"小黑", 18} //有序赋值,并且必须包含所有字段,否则报错
p2 := Person{Age: 18} //关键词赋值,未赋值字段有空值
fmt.Println(p1)
fmt.Println(p2)
}
练习struct
package main import "fmt" //声明结构体名称Stu
type Stu struct {
Name string //结构体字段
Age int //如未赋值有默认空值
Address string
Score int
} //结构体可以定义复杂的类型
type Person struct {
Name string
Age int
Score [5]float64 //容量为5的数组
prt *int //指针类型
slice []int //int类型切片
map1 map[string]string //map类型字段
//slice和map默认值是nil,必须make初始化才可使用
} //结构体是值类型,不同结构体实例之间互不影响
type Monster struct {
Name string
Age int
} func main() {
//声明结构体类型变量
var stu1 Stu
//结构体可以通过 . 的方式赋值,声明赋值方式一
stu1.Name = "小黑"
stu1.Age = 18
stu1.Address = "沙河"
stu1.Score = 100
fmt.Printf("stu1的名字=%v 年纪=%v 住址=%v 分数=%v\n", stu1.Name, stu1.Age, stu1.Address, stu1.Score) //声明赋值方式二
monster1 := Monster{"红孩儿", 18}
monster2 := Monster{"女妖怪", 999}
//两个结构体实例,内存地址不一样,确保独立
fmt.Printf("monster1地址:%p\n", &monster1)
fmt.Printf("monster2地址:%p\n", &monster2) //声明方式三
//用来分配内存,主要用来分配值类型,比如int、struct。返回指向类型的 指针
//此时m1是一个指针
var m1 *Monster = new(Monster)
//给m1赋值
(*m1).Name = "孙悟空" //编译器自动识别 同于 m1.Name="孙悟空"
(*m1).Age = 9999 //同上
fmt.Println(*m1) //此时m1是指针变量,加上*取值 //声明方式四
m2 := &Monster{
"猪八戒",
888,
}
fmt.Println(*m2)
//第三、第四种返回结构体指针,go编译器自动识别,简化程序员心智负担,建议用1、2方法
}
4.1.1. 匿名结构体
没有名字的结构体
package main import "fmt" func main() {
//匿名函数
func() {
fmt.Println("我是匿名函数")
}()
//匿名结构体
p1 := struct {
name string
age int
}{
name: "张三",
age: 18,
}
fmt.Println(p1)
}
4.1.2. 匿名字段
package main import "fmt" func main() {
type student struct {
string //匿名字段,类型当做字段名
int
}
s1 := student{
"吴亦凡",
18,
}
fmt.Println(s1.string, s1.int)
}
4.1.3. 结构体嵌套
面向对象:聚合关系
一个类作为另一个类的属性
package main import "fmt" type Book struct {
bookName string
price float64
author string
} type Person struct {
name string
age int
book Book //继承Book结构体的字段 ,模拟聚合关系
} func main() {
//先定义好的book对象
b1 := Book{"如何找到女朋友", 999.999, "alex金角大王"}
p1 := Person{"武沛奇", 26, b1} //b1就是Book结构体类型,武沛奇买了一本书
fmt.Printf("姓名:%s,年纪:%d,书名:%s,价格:%.2f,书的作者:%s\n", p1.name, p1.age, p1.book.bookName, p1.book.price, p1.book.author) //声明初始化book对象,一行搞定
p2 := Person{"萧峰", 25, Book{"如何找到男朋友", 3.58, "超哥著作"}}
fmt.Printf("姓名:%s,年纪:%d,书名:%s,价格:%.2f,书的作者:%s\n", p2.name, p2.age, p2.book.bookName, p2.book.price, p2.book.author)
}
结构体嵌套练习
学生与书架
package main import "fmt" type Book struct {
bookName string
price float64
}
type Student struct {
name string
age int
books []*Book
} func main() {
b1 := Book{"霸道总裁爱上我", 120.22}
b2 := Book{"斗破苍穹", 12.5}
b3 := Book{"我和师姐的故事", 15.5}
//定义书架,默认没有书,可以容纳10本书
//用Book就是值拷贝,*Book就是放入书的内存地址
bookSlice := make([]*Book, 0, 10)
//注意需要传入地址
bookSlice = append(bookSlice, &b1, &b2, &b3)
//创建一个学生
s1 := Student{"小猪沛奇", 3, bookSlice}
fmt.Printf("姓名:%s,年纪:%d\n", s1.name, s1.age)
//查看书架上书的信息
for i := 0; i < len(s1.books); i++ {
book := s1.books[i]
fmt.Printf("\t第%d本书,书名:%s,书价格:%.2f\n", i+1, (*book).bookName, book.price)
} //创建图书方式二
//初始化创建时候,必须对切片分配内存
s2 := Student{"特斯拉车主alex", 46, make([]*Book, 0, 10)}
//放入书架的书,放入书的内存地址
s2.books = append(s2.books, &Book{"斗罗大陆", 55.3}, &Book{"python入门到放弃", 1.28}, &Book{"王思聪与三个网红的一天", 999999.99})
fmt.Printf("学生名:%s,学习年龄:%d\n", s2.name, s2.age)
//输入所有s2学生看的书
for k, v := range s2.books {
fmt.Printf("\t第%d本书,书名:%s,价格:%.2f\n", k+1, v.bookName, v.price)
}
}
4.1.4. 面向对象:继承关系
一个类作为另一个类的子类:子类,父类
继承:面向对象的第二个特征,用于描述两个类的关系
子类,派生类,subClass继承父类(超类,基类,superClass)
子类可以直接访问父类已有的属性和方法
子类可以新增自己的属性和方法
子类也可以重写父类已有的方法
通过匿名字段的方式,进行嵌套,实现继承关系
package main import "fmt" //1.定义父类
type Person struct {
name string
age int
} //2定义子类,匿名字段,Person即是
type Son struct {
Person //模拟继承结构,继承父类的name,age属性
school string //子类的新增属性
} func main() {
//父类
p1 := Person{"李靖", 999}
fmt.Println(p1.name, p1.age)
//子类赋值方式一,子类直接访问父类属性
var s2 Son
s2.name = "娜扎"
s2.age = 666
s2.school = "神仙学校"
fmt.Println(s2, s2.name, s2.age, s2.school)
//创建方式二,简写方式
s3 := Son{Person{"木吒", 667}, "神仙学校"}
fmt.Println(s3, s3.name, s3.age, s3.school) //创建方式三,基于key-value写
s4 := Son{Person: Person{name: "金吒", age: 668}, school: "神仙学校"}
fmt.Println(s4, s4.name, s4.age, s4.school)
}
4.1.5. 结构体细节
- 结构体字段在内存中是连续的
package main import "fmt" type Test struct {
A int32
B int32
C int32
D int32
} func main() {
var t Test
fmt.Printf("a addr:%p\n", &t.A)
fmt.Printf("b addr:%p\n", &t.B)
fmt.Printf("c addr:%p\n", &t.C)
fmt.Printf("d addr:%p\n", &t.D)
}
- 结构体由用户自定义,可以类型转换,但必须完全相同字段、个数、类型
- 对结构体进行重新定义(重新type),效果同于结构体
别名
- struct每个字段,可以写一个tag,这个tab可以通过反射获取,用在序列化,反序列化
package main import (
"encoding/json"
"fmt"
) type User struct {
UserName string `json:"姓名"` //反引号括起来的就是struct tag
Sex string `json:"性别"`
Score float32 `json:"成绩"`
Age int32 `json:"年纪"`
} func main() {
user := &User{
UserName: "user01",
Sex: "男",
Score: 99.2,
Age: 18,
}
//将user变量序列化为json格式字符串
data, _ := json.Marshal(user)
fmt.Printf("json str:%s\n", string(data))
}
4.2. 结构体内存分配
先看代码
package main import "fmt" type Person struct {
Name string
Age int
} func main() {
//p1有自己的结构体内存地址,
var p1 Person
p1.Age = 10
p1.Name = "王大锤" //定义P2 指针类型,指向p1的内存地址
var p2 *Person = &p1
//两种形式一样,go编译器自动识别
fmt.Println((*p2).Age)
fmt.Println(p2.Age)
//修改p2的结构体值,也就是修改了p1的结构体值
p2.Name = "葫芦娃"
fmt.Printf("输出结果 p2.Name=%v p1.Name=%v\n", p2.Name, p1.Name)
fmt.Printf("输出结果(*p2).Name=%v p1.Name=%v\n", (*p2).Name, p1.Name) //查看p1和p2的内存地址
fmt.Printf("p1内存地址%p\n", &p1)
//p2是指针变量,自己也有一块内存地址,p2的值指向
fmt.Printf("p2内存地址%p p2的值是%v\n", &p2, p2)
}
4.3. 结构体内存分布原理图
3.11 Go Struct结构体的更多相关文章
- Swift Struct 结构体
前言 Swift 语言有两种基本的数据类型,即类(class)和结构体(struct),class 这样的概念大家不会陌生,而 struct 也并不是什么新的概念,在 Objective-C 和 C ...
- go struct结构体
struct结构体 用来自定义复杂数据结构 struct里面可以包含多个字段(属性),字段可以是任意类型 struct类型可以定义方法,注意和函数的区分 struct类型是值类型 struct类型可以 ...
- C# Struct结构体里数组长度的指定
typedef struct Point{ unsigned short x; unsigned short y; }mPoint;//点坐标 typedef struct Line{ mPoint ...
- C#基础--struct(结构体)
结构体和类有点类似 我们定义一个类的时候 是class 类名 定义结构体的时候是 struct 结构体名 结构体的写法 struct Point { // public int ...
- 1.0 基础、标示符、常量、数据类型(enum 枚举,struct 结构体)、操作符、循环、数组
一.程序 现实生活中,程序是指完成某些事务的一种既定方法和过程,可以把程序看成是一系列动作执行过程的描述. 在计算机世界,程序是指令,即为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集 ...
- C#语言struct结构体适用场景和注意事项
在C#语言中struct结构体和class之间的区别主要是值类型和引用类型的区别,但实际上如果使用不当是非常要命的.从Win32时代过来的人对于struct一点不感觉陌生,但是却反而忽略了一些基本问题 ...
- C语言 Struct 结构体在 Java 中的体现
大一整个学期完成了 C 语言的学习,大二就进入了Java 的学习. 和C语言一样,我们都会尝试写一个小小的学生管理系统什么的,学习过 C 语言同学知道,在管理系统中 Struct 结构体是个很好用的东 ...
- struct 结构体解析(原)
(一)基本概念 结构体是一个或是多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组合在一个名字之下.我们将关键字struct引入了结构声明中.结构声明包含在花括号内的一系列声明组成 ...
- struct结构体在c和c++中的差别
非常多次遇到这个struct的问题,今天在这里简单总结一下我的理解 一.struct在C 中的使用 1.单独使用struct定义结构体类型 struct Student { int id; int n ...
随机推荐
- 徐州赛区网络预赛 D Easy Math
比赛快结束的适合看了一下D题,发现跟前几天刚刚做过的HDU 5728 PowMod几乎一模一样,当时特兴奋,结果一直到比赛结束都一直WA.回来仔细一琢磨才发现,PowMod这道题保证了n不含平方因子, ...
- 飞机大战-面向对象-pygame
飞机大战 最近学习了python的面向对象,对面向对象的理解不是很深刻. 面向对象是数据和函数的'打包整理',将相关数据和处理数据的方法集中在一个地方,方便使用和管理. 本着学习的目的,在网上找了这个 ...
- Burnside&Polya总结
这里就算是一个小总结吧- 附参考的网址: http://blog.sina.com.cn/s/blog_6a46cc3f0100s2qf.html http://www.cnblogs.com/han ...
- Tomcat中的类是怎么被一步步加载的?
了解Tomcat的类加载机制,原来一切是这么的简单. 一.类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加载. 比如JVM启动时,会通过不同的类加载器加载不同的类.当用 ...
- [开发笔记]-unix时间戳、GMT时间与datetime类型时间之前的转换
前段时间项目中涉及到了MySql和MsSql数据类型之间的转换,最近又在研究新浪微博的API,涉及到了带有时区的GMT时间类型的转换,所以,特记录于此,以备日后查询. 一:UNIX时间戳与dateti ...
- MYSQl 全表扫描以及查询性能
MYSQl 全表扫描以及查询性能 -- 本文章仅用于学习,记录 一. Mysql在一些情况下全表检索比索引查询更快: 1.表格数据很少,使用全表检索会比使用索引检索更快.一般当表格总数据小于10行并且 ...
- 数论--HDU 1495 非常可乐
Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和se ...
- POJ 3581 Prime Gap(二分)
Prime Gap Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 11009 Accepted: 6298 Descriptio ...
- SpringBoot:整合Shiro
目录 1.Shiro简介 1.1.什么是Shiro? 1.2.有哪些功能 1.3.Shiro架构(外部) 1.4.Shiro架构(内部) 2.HelloWorld 3.Shiro整合Spring Bo ...
- Python3 迭代器与生成器 - 学习笔记
可迭代对象(Iterable) 迭代器(Iterator) 定义 迭代器和可迭代对象的区别 创建一个迭代器 创建一个迭代器类 使用内置iter()函数 StopIteration异常 生成器(gene ...