结构体
//定义结构体类型
type Person struct {
name string
age int
height float64
}
//定义结构体变量
var student Person
//给结构体属性赋值
student.name = "zhangsan"
student.age = 20
student.height = 170.0
//打印结构体
Println(student)总结:
1.Go语言中的结构体几乎和C语言中的结构体一模一样
都需要先定义结构体类型, 再定义结构体变量
都是用来保存一组不同类型数据的2.C语言定义结构体类型的格式
struct 结构体类型名称{
属性名称 属性类型;
属性名称 属性类型;
}
3.Go语言定义结构体类型的格式
typd 结构体类型名称 struct{
属性名称 属性类型;
属性名称 属性类型;
}4.C语言中通过结构体类型定义结构体变量, 必须拷贝struct
struct 结构体类型名称 结构体变量名称;5.Go语言中通过结构体类型定义结构体变量, 不用拷贝struct
var 结构体变量名称 结构体类型名称6.和C语言中的结构体一样, 可以定义结构体变量的同时初始化, 也可以先定义结构体变量再初始化
注意点:
和切片以及字典不一样, 结构体变量定义之后就可以直接使用了结构体与函数
//定义结构体类型
type Person struct {
name string
}
func main() {
// 总结:结构体类型和数组一样都是值传递,修改形参的不会影响到实参
//定义结构体变量
var people Person
//给结构体变量赋值
people.name = "张三"
//调用change函数
change(people)
//打印结构体
Println(people)
}
func change(people Person) {
people.name = "李四"
}
结构体中含有切片,字典
func main() {
type Person struct {
age int
score float32
name string
arr [3]int
sce []int
dict map[string]string
}
var per Person
// 常规的数据类型, 我们都可以直接操作, 完全没有问题
per.age = 18
per.score = 100
per.name = "lnj"
per.arr[0] = 1
per.arr[1] = 3
per.arr[2] = 5
fmt.Println(per)
// 注意点: 如果结构体的属性是切片和字典类型, 那么就不能直接操作
// 必须先给切片初始化(创建切片)
per.sce = make([]int, 2)
per.sce[0] = 123
per.sce[1] = 456
//per.sce[2] = 789 // 通过索引操作切片, 不能超出切片的长度
fmt.Println(per)
per.dict = make(map[string]string)
per.dict["name"] = "zs"
fmt.Println(per)
}结构体类型之间转换
func main() {
/*
结构体变量之间可以相互转换, 但是必须保证结构体类型的
属性名称 属性类型 属性顺序 属性的个数 都一样
*/
type Person1 struct {
name string
age int
}
// 属性顺序不同
type Person2 struct {
age int
name string
}
// 如果属性名称和类型都一样, 但是顺序不一样, 不能转换
//var p1 Person1 = Person1{}
//var p2 Person2
//p2 = Person2(p1)
//fmt.Println(p1)
//fmt.Println(p2)
type Person3 struct {
name1 string
age int
}
// 如果属性的类型和顺序都一样, 但是名称不一样, 不能转换
//var p1 Person1 = Person1{}
//var p2 Person3
//p2 = Person3(p1)
//fmt.Println(p1)
//fmt.Println(p2)
type Person4 struct {
name string
age int
score int
}
// 如果属性的名称和类型都一样, 但是个数不一样, 不能转换
//var p1 Person1 = Person1{}
//var p2 Person4
//p2 = Person4(p1)
//fmt.Println(p1)
//fmt.Println(p2)
type Person5 struct {
name [10]byte
age int
}
// 如果属性名称和个数都一样, 但是属性数据类型不一样, 不能转换
//var p1 Person1 = Person1{}
//var p2 Person5
//p2 = Person5(p1)
//fmt.Println(p1)
//fmt.Println(p2)
type Person6 struct {
name string
age int
}
// 只有属性个数, 属性名称, 属性类型, 属性属性都一样, 才能转换
var p1 Person1 = Person1{}
var p2 Person6
p2 = Person6(p1)
fmt.Println(p1)
fmt.Println(p2)
}
结构体匿名属性
func main() {
/*
1.什么是匿名结构体属性?
没有名称的属性就是匿名属性
2.如何操作匿名属性?
匿名属性的数据类型就是匿名属性的名称, 所以可以通过匿名属性的数据类型来操作
3.匿名属性一般都用于结构体的嵌套定义
结构体的属性又是一个结构体
*/
/*
type Person struct {
int // 只有数据类型, 没有名称, 就是匿名属性
name string
}
//var per Person = Person{666, "lnj"}
//fmt.Println(per)
var per Person
per.int = 666
per.name = "lnj"
fmt.Println(per)
*/
type Date struct {
year int
month int
day int
}
type Person struct {
name string
//year int
//month int
//day int
Date
}
type Animal struct {
name string
//year int
//month int
//day int
Date
}
//var per Person
//per.name = "zs"
//per.Date = Date{2012, 12,12}
//fmt.Println(per) // {zs {2012 12 12}}
var per Person = Person{"zs", Date{2012, 12, 12}}
fmt.Println(per) // {zs {2012 12 12}}
}
结构体嵌套
func main() {
/*
第一种方式
type 结构体名称1 struct{
}
type 结构体名称2 struct{
结构体名称1
}
第二种方式
type 结构体名称1 struct{
}
type 结构体名称2 struct{
结构体名称1
}
type 结构体名称3 struct{
结构体名称2
}
第三种方式
type 结构体名称1 struct{
}
type 结构体名称2 struct{
}
type 结构体名称3 struct{
结构体名称1
结构体名称2
}
*/
// 第一种方式: 没有重名属性的情况
/*
type Person struct {
name string
age int
}
type Student struct {
Person
score float32
}
stu := Student{Person{"zs", 18}, 99.5}
fmt.Println(stu)
// 结构体嵌套定义时, 如果操作结构体的属性
//fmt.Println(stu.Person.name)
//fmt.Println(stu.Person.age)
//fmt.Println(stu.score)
// 第二种访问的方式
// 会先去Student结构体中查询有没有name属性, 如果有就直接访问
// 如果没有会继续查找嵌套的匿名结构体中有没有, 如果有就访问匿名结构体中的name属性
//fmt.Println(stu.name)
//fmt.Println(stu.age)
//fmt.Println(stu.score)
*/
// 第一种方式: 有重名属性的情况
/*
type Person struct {
name string
age int
}
type Teacher struct {
Person
name string
title string
}
tea := Teacher{Person{"lnj", 33}, "zs", "老师"}
fmt.Println(tea)
fmt.Println(tea.name) // zs
fmt.Println(tea.Person.name) // lnj
*/
// 第二种方式: 没有重名属性的情况
/*
type Object struct {
name string
}
type Person struct {
Object
age int
}
type Student struct {
Person
score float32
}
stu := Student{Person{Object{"zs"}, 18}, 99.5}
fmt.Println(stu) // {{{zs} 18} 99.5}
fmt.Println(stu.score)
fmt.Println(stu.Person.age)
fmt.Println(stu.age)
fmt.Println(stu.Person.Object.name)
fmt.Println(stu.Person.name)
fmt.Println(stu.name)
*/
// 第二种方式: 有重名属性的情况
/*
type Object struct {
name string
}
type Person struct {
Object
name string
age int
}
type Student struct {
Person
name string
score float32
}
stu := Student{Person{Object{"lnj"}, "zs", 18}, "ww", 99.5}
fmt.Println(stu)
fmt.Println(stu.name) // ww
fmt.Println(stu.Person.name) // zs
fmt.Println(stu.Person.Object.name) // lnj
*/
// 第三种方式: 没有重名属性的情况
/*
type Object struct {
name string
}
type Person struct {
age int
}
type Student struct {
Object
Person
score float32
}
stu := Student{Object{"lnj"}, Person{18}, 99.5}
fmt.Println(stu)
fmt.Println(stu.Object.name)
fmt.Println(stu.name)
fmt.Println(stu.Person.age)
fmt.Println(stu.age)
*/
type Object struct {
name string
}
type Person struct {
name string
}
type Student struct {
Object
Person
name string
score float32
}
stu := Student{Object{"zs"}, Person{"ls"}, "lnj",99.5}
fmt.Println(stu.name)
fmt.Println(stu.Object.name)
fmt.Println(stu.Person.name)
}