GO基础之结构体
1 、什么是结构体
GO语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
2、什么是实例化?
- Go结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正分配内存。因此必须在定义结构体并实例化后才能使用结构体实例化就是根据结构体定义的格式创建一份与格式一致的內存区域。
- 结构体实例之间的内存是完全独立的。
package main import "fmt" func main() {
//实例化方式一
var stu1 Student
fmt.Printf("stu1=%T,%v,%q \n", stu1, stu1, stu1)
stu1.name = "zs"
stu1.age =
stu1.sex =
fmt.Printf("stu1=%T,%v,%q \n", stu1, stu1, stu1)
//实例化方式二
stu2 := Student{}
stu2.name = "David"
stu2.age =
stu2.sex =
fmt.Printf("stu2=%T,%v,%q \n", stu2, stu2, stu2)
//实例化方式三
stu3 := Student{
name: "Josh",
age: ,
sex: ,
}
fmt.Printf("stu3=%T,%v,%q \n", stu3, stu3, stu3)
//实例化四
stu4 := Student{"Ruby", , }
fmt.Printf("stu3=%T,%v,%q \n", stu4, stu4, stu4)
//实例化五
//使用内置函数new()对结构体进行实例化,结构体实例化后形成指针类型的结构体
//·new内置函数会分配内存。第一个参数是类型,而不是值,返回的值是指向该类型新分配的零值的指针。该函数用于创建某个类型的指针。
stu5 := new(Student)
(*stu5).name = "Running"
(*stu5).age =
stu5.sex = //语法糖的方式
fmt.Printf("stu3=%T,%v,%q \n", stu5, stu5, stu5) //stu3=*main.Student,&{Running 31 0},&{"Running" '\x1f' '\x00'} } //结构体的定义
type Student struct {
name string
age int
sex int8
}
语法糖的概念( Syntactic sugar)
- 语法糖,也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达( PeterJ.Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。
- 通常来说使用语法糖能够增加程序的可读性,从而减少程序代码岀错的机会
- 结构体和数组中都含有语法糖。
package main import "fmt" func main() {
arr := []int{, , , }
arr2 := &arr
fmt.Println((*arr2)[])
//数组中的语法糖
fmt.Println(arr2[]) //切片
arr3 := []int{, , , }
arr4 := &arr3
fmt.Println((*arr4)[])
//切片中没有语法糖
//fmt.Println(arr4[3])
}
3、结构体是值类型传递
二、深拷贝与浅拷贝
struct 默认是深拷贝
package main import "fmt" func main() {
stu1 := Student{"zs", , }
fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1)
//stu1:=main.Student,0xc0000044a0,{zs 18 0}
stu2 := stu1
stu2.name = "ls"
fmt.Printf("stu2:=%T,%p,%v \n", stu2, &stu2, stu2)
//stu2:=main.Student,0xc000004520,{ls 18 0} fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1)
//stu1:=main.Student,0xc0000044a0,{zs 18 0}
//修改stu2对stu1没有任何影响 }
实现浅拷贝
1、直接赋值指针地址
package main import "fmt" func main() {
stu1 := Student{"zs", , }
fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1)
//stu1:=main.Student,0xc00005a440,{zs 18 0}
stu2 := &stu1
stu2.name = "ls"
fmt.Printf("stu2:=%T,%p,%v \n", stu2, stu2, stu2)
//stu2:=*main.Student,0xc00005a440,&{ls 18 0} fmt.Printf("stu1:=%T,%p,%v \n", stu1, &stu1, stu1)
//stu1:=main.Student,0xc00005a440,{ls 18 0}
//修改stu2对stu1有影响
}
2、实现结构体浅拷贝:通过new()函数来实例化对象
package main import "fmt" func main() {
//3、实现结构体浅拷贝:通过new()函数来实例化对象
d4 := new(Dog)
d4.name = "多多"
d4.color = "棕色"
d4.age =
d4.kind = "巴哥犬"
d5 := d4
fmt.Printf("d4: %T , %v , %p \n", d4, d4, d4)
//d4: *main.Dog , &{多多 棕色 1 巴哥犬} , 0xc000040080
fmt.Printf("d5: %T , %v , %p \n", d5, d5, d5) fmt.Println("--------------------------------------") d5.color = "金色"
d5.kind = "金毛"
fmt.Println("d5修改后:", d5)
//d5修改后: &{多多 金色 1 金毛}
fmt.Println("d4:", d4)
//d4: &{多多 金色 1 金毛}
} type Dog struct {
name string
color string
age int8
kind string
}
三、struct做函数参数
结构体对象或指针作为函数的参数及函数返回值
- 结构体对象作为函数参数与结构体指针作为函数参数的不同
- 结构体对象作为函数返回值与结构体指针作为函数返回值的不同
四、匿名结构体和匿名字段
匿名结构体
- •没有名字的结构体。无需通过type关键字定义就可以直接使用。
- •在创建匿名结构体时,同时要创建对象。
- •匿名结构体由结构体定义和键值对初始化两部分组成
//匿名结构体
addr := struct {
province, city string
}{"陕西省", "西安市"}
fmt.Println(addr)
结构体的匿名字段
结构体中的字段没有名字,只包含一个没有字段名的类型。这些字段被称为匿名字段。
- •如果字段没有名字,那么默认使用类型作为字段名。
- •注意:同一个类型只能写一个。
- •结构体嵌套中采用匿名结构体字段可以模拟继承关系。
package main import "fmt" type User struct {
string
byte
int8
float64
} func main() {
// 实例化结构体
user:= User{"Steven" , 'm' , , 177.5}
fmt.Println(user)
//如果想依次输出姓名、年龄、身高、性别
fmt.Printf("姓名:%s \n" , user.string)
fmt.Printf("身高:%.2f \n" , user.float64)
fmt.Printf("性别:%c \n" , user.byte)
fmt.Printf("年龄:%d \n" , user.int8)
}
五、结构体的聚合
•将一个结构体作为另一个结构体的属性(字段),这种结构就是结构体嵌套。
•结构体嵌套可以模拟面向对象中的两种关系:
- 〇聚合关系:一个类作为另_个类的属性
- 〇继承关系:一个类作为另一个类的子类。子类和父类。
package main import "fmt" type Address struct {
province, city string
} type Person struct {
name string
age int
address *Address
} func main() {
//模拟结构体对象之间的聚合关系
p := Person{}
p.name = "Steven"
p.age = //赋值方式1:
addr := Address{}
addr.province = "北京市"
addr.city = "海淀区"
p.address = &addr fmt.Println(p)
fmt.Println("姓名:", p.name)
fmt.Println("年龄:", p.age)
fmt.Println("省:", p.address.province)
fmt.Println("市:", p.address.city)
fmt.Println("-----------------------") //修改Person对象的数据,是否会影响Address对象的数据?
p.address.city = "昌平区"
fmt.Println("姓名:", p.name)
fmt.Println("年龄:", p.age)
fmt.Println("省:", p.address.province)
fmt.Println("市:", p.address.city)
fmt.Println("addr市:", addr.city) //?是否会受到影响?
fmt.Println("-----------------------") //修改Address对象的数据,是否会影响Person对象的数据?
addr.city = "大兴区"
fmt.Println("姓名:", p.name)
fmt.Println("年龄:", p.age)
fmt.Println("省:", p.address.province)
fmt.Println("市:", p.address.city)
fmt.Println("addr市:", addr.city) //?是否会受到影响?
fmt.Println("-----------------------") //赋值方式2
p.address = &Address{
province: "陕西省",
city: "西安市",
}
fmt.Println(p)
fmt.Println("姓名:", p.name)
fmt.Println("年龄:", p.age)
fmt.Println("省:", p.address.province)
fmt.Println("市:", p.address.city)
fmt.Println("-----------------------")
}
六、结构体嵌套模拟继承关系
•继承是传统面向对象编程中三大特征之一。用于描述两个类之间的关系。一个类(子类、派生类)继承于另一个类(父类、超类)。
•子类可以有自己的属性和方法,也可以重写父类已有的方法。
•子类可以直接访问父类所有的属性和方法。
•提升字段:
〇在结构体中属于匿名结构体的字段称为提升字段,因为它们可以被访问,就好像它们属于拥有匿名结构字段的结构一样。
〇换句话说,父类中的字段就是提升字段。
•继承的意义:避免重复代码、扩展类的功能
•采用匿名字段的形式就是模拟继承关系。而模拟聚合关系时一定要采用有名字的结构体作为字段
package main import (
"fmt"
) type Person struct {
name string
age int
sex string
} type Student struct {
Person
schoolName string
} func main() {
//1、实例化并初始化Person
p1 := Person{"Steven", , "男"}
fmt.Println(p1)
fmt.Println("-------------------") //2、实例化并初始化Student
// 写法1:
s1 := Student{p1, "北航软件学院"}
printInfo(s1) //写法2:
s2 := Student{Person{"Josh", , "男"}, "北外高翻学院"}
printInfo(s2) //写法3:
s3 := Student{Person: Person{
name: "Penn",
age: ,
sex: "男",
},
schoolName: "北大元培学院",
}
printInfo(s3) // 写法4:
s4 := Student{}
s4.name = "Daniel"
s4.sex = "男"
s4.age =
s4.schoolName = "北京十一龙樾"
printInfo(s4) } func printInfo(s1 Student) {
fmt.Println(s1)
fmt.Printf("%+v \n", s1)
fmt.Printf("姓名:%s, 年龄:%d , 性别:%s ,学校:%s \n", s1.name, s1.age, s1.sex, s1.schoolName)
fmt.Println("-------------------")
}
七、结构体中的方法
• Go语言同时有函数和方法,方法的本质是函数,但是方法和函数又具有不同点。
1、 含义不同
•函数function是一段具有独立功能的代码,可以被反复多次调用,从而实现代码复用。而方法method是一个类的行为功能,只有该类的对象才能调用。
2、 方法有接受者,而函数无接受者
• Go语言的方法methods—种作用于特定类型变量的函数。这种特定类型变量叫做Receiver (接受者、接收者、接收器)。
•接受者的概念类似于传统面向对象语言中的this或self关键字。
• Go语言的接受者强调了方法具有作用对象,而函数没有作用对象。
•—个方法就是一个包含了接受者的函数。
• Go语言中,接受者的类型可以是任何类型,不仅仅是结构体,也可以是struct类型外的其他任何类型。
3、 函数不可以重名,而方法可以重名
•只要接受者不同,则方法名可以一样。
package main import "fmt"
import "base"
type Employee struct {
name , currency string
salary float64
}
func main() {
emp1 := Employee{"Daniel" , "$" , }
emp1.printSalary()//员工姓名:Daniel ,薪资:$2000.00
emp1.updateSalary()
emp1.printSalary()//员工姓名:Daniel ,薪资:$1000.00
} //printSalary方法
func (e Employee) printSalary() {
fmt.Printf("员工姓名:%s ,薪资:%s%.2f \n", e.name , e.currency , e.salary)
}
func (e *Employee) updateSalary(num float64) {
e.salary=num
}
方法的继承与重写
package main import "fmt"
import "base" type Human struct {
name, phone string
age int
} type Student struct {
Human
school string
} type Employee struct {
Human
company string
} func main() {
s1 := Student{Human{"Daniel", "", }, "十一龙樾"}
e1 := Employee{Human{"Steven", "", }, "1000phone"}
s1.printName()
e1.printName()
s1.SayHi()
e1.SayHi()
}
//======================方法的继承=============================
func (h *Human) printName() {
fmt.Println("大家好!我是%s ", h.name)
} //=====================方法的重写=============================
func (h *Human) SayHi() {
fmt.Printf("大家好!我是%s , 我%d岁 , 联系方式:%s \n", h.name, h.age, h.phone)
} func (s *Student) SayHi() {
fmt.Printf("大家好!我是%s , 我%d岁 , 我在%s上学,联系方式:%s \n", s.name, s.age, s.school, s.phone)
} func (e *Employee) SayHi() {
fmt.Printf("大家好!我是%s , 我%d岁 , 我在%s工作,联系方式:%s \n", e.name, e.age, e.company, e.phone)
}
GO基础之结构体的更多相关文章
- Go语言基础之结构体
Go语言基础之结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 类型别名和自定义类型 自定义类型 在G ...
- GO学习-(13) Go语言基础之结构体
Go语言基础之结构体 Go语言中没有"类"的概念,也不支持"类"的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. ...
- Go基础之--结构体和方法
结构体的定义 结构体是将零个或者多个任意类型的命令变量组合在一起的聚合数据类型.每个变量都叫做结构体的成员. 其实简单理解,Go语言的结构体struct和其他语言的类class有相等的地位,但是GO语 ...
- C#基础--struct(结构体)
结构体和类有点类似 我们定义一个类的时候 是class 类名 定义结构体的时候是 struct 结构体名 结构体的写法 struct Point { // public int ...
- Swift超详细的基础语法-结构体,结构体构造器,定义成员方法, 值类型, 扩充函数
知识点 基本概念 结构体的基本使用 结构体构造器(构造函数/构造方法) 结构体扩充函数(方法), 又称成员方法 结构体是值类型 1. 基本概念 1.1 概念介绍 结构体(struct)是由一系列具有相 ...
- go语言基础之结构体做函数参数 值传递和地址传递
1.结构体做函数参数值传递 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...
- go语言基础之结构体比较和赋值
1.结构体比较和赋值 (同类型的结构体可以相互赋值) 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Stud ...
- go语言基础之结构体成员的使用指针变量
1.结构体成员的使用:指针变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct ...
- go语言基础之结构体成员的使用普通变量
1.结构体成员的使用普通变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...
- go语言基础之结构体普通变量初始化
1.结构体 1.1.结构体类型 有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性.显然单独定义以上变量比较繁琐,数据不便于管理. 结构体是一种聚合的数 ...
随机推荐
- SpringCloud -创建统一的依赖管理
场景 Spring Cloud 为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,控制总线,一次性 Token,全居琐,Leader 选举,分布式 Session,集群状态)中快速构 ...
- Android 基于ksoap2的webservice请求的学习
[学习阶段] WebService网络请求? 其实我也是第一次遇到,之所以有这个需要是因为一些与 ERP 相关的业务,需要用到这样的一个请求方式. 开始学习WebService ①当然是百度搜索,这里 ...
- LAMP环境搭建与配置(1)
安装和配置MySQL.Apache.PHP 概念 LAMP是Linux Apache MySQL PHP 的简写,把Apache.MySQL以及PHP安装在Linux系统上,组成一个环境来运行PHP的 ...
- 剑指offer-36:数组中的逆序对
参考:1. https://www.geeksforgeeks.org/merge-sort/ 2.<剑指Offer:名企面试官精讲典型编程题> 题目描述 在数组中的两个数字,如果前面一个 ...
- 一个故事搞懂Java并发编程
最近在给别人讲解Java并发编程面试考点时,为了解释锁对象这个概念,想了一个形象的故事.后来慢慢发现这个故事似乎能讲解Java并发编程中好多核心概念,于是完善起来形成了了这篇文章.大家先忘记并发编程, ...
- Android odex,oat文件的反编译,回编译
现在,许多Android手机的ROM包在生成过程中都启用优化,把jar文件抽空,生成odex/oat和vdex文件,以在运行时省掉编译时间.如果想对这些jar进行修改,就要修改它们所对应的odex或者 ...
- JavaBean动态添加删除属性
1.cglib BeanGenerator beanGenerator = new BeanGenerator(); beanGenerator.addProperty("id", ...
- 1.编译spring源码
本文是作者原创,版权归作者所有.若要转载,请注明出处 下载spring源码,本文用的是版本如下: springframework 5.1.x, IDE工具idea 2019.2.3 JAVA ...
- jsp + js + 前端弹出框
在项目中,前端页面我们时常需要各种各样的弹出框: 1.alert对话框:显示含有给定消息的"JavaScript Alert"对话框 代码: var a = "Hello ...
- AndroidStudio集成.so遇见的问题:关于java.lang.UnsatisfiedLinkError: Native method not found
我调试的是串口程序,程序中需要继承.so文件,AndroidStudio中集成.so文件的方法是将存放.so的文件夹(通常这个文件夹名字是:armeabi)拷贝到app的libs文件夹中,然后在app ...