1、结构体基础
package main
func main() {
/*
1.Go语言中的结构体几乎和C语言中的结构体一模一样
都需要先定义结构体类型, 再定义结构体变量
都是用来保存一组不同类型数据的
2.C语言定义结构体类型的格式
struct 结构体类型名称{
属性名称 属性类型;
属性名称 属性类型;
}
3.Go语言定义结构体类型的格式
type 结构体类型名称 struct{
属性名称 属性类型;
属性名称 属性类型;
}
4.C语言中通过结构体类型定义结构体变量, 必须拷贝struct
struct 结构体类型名称 结构体变量名称;
5.Go语言中通过结构体类型定义结构体变量, 不用拷贝struct
var 结构体变量名称 结构体类型名称
6.和C语言中的结构体一样, 可以定义结构体变量的同时初始化, 也可以先定义结构体变量再初始化
注意点:
和切片以及字典不一样, 结构体变量定义之后就可以直接使用了
*/
/*
// 1.定义一个结构体类型
type Person struct{
name string
age int
}
// 2.通过结构体类型定义结构变量
var per Person
per.name = "msh"
per.age = 18
fmt.Println(per)
*/
/*
type Person struct{
name string
age int
}
// 定义的同时初始化
//var per Person = Person{"msh", 18}
//fmt.Println(per)
// 先定义再初始化
var per Person
//per = Person{"msh", 18} // 完全初始化
//per = Person{"msh"} // error 部分初始化, 必须通过属性名称指定要给谁初始化
per = Person{name:"msh"} // 部分初始化, 必须通过属性名称指定要给谁初始化
fmt.Println(per)
*/
}
package main
import "fmt"
// 1.定义一个结构体类型
type Person struct {
name string
age int
}
func main() {
// 结构体和函数: 结构体类型和数组类型一样, 在Go语言中都是值传递
// 修改形参不会影响到实参
// 2.定义一个结构体变量
p1 := Person{"msh", 18}
//// 3.再定义一个结构体变量
//var p2 Person
//// 4.将p1赋值给p2
//p2 = p1
//// 5.修改p2的值
//fmt.Println(p1)
//p2.name = "zs"
//fmt.Println(p1)
fmt.Println(p1)
change(p1)
fmt.Println(p1)
}
func change(pp Person) {
pp.name = "zs"
}
package main
import "fmt"
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 = "msh"
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)
}
2、结构体之间的转换
package main
import "fmt"
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)
}
3、匿名属性
package main
import "fmt"
func main() {
/*
1.什么是匿名结构体属性?
没有名称的属性就是匿名属性
2.如何操作匿名属性?
匿名属性的数据类型就是匿名属性的名称, 所以可以通过匿名属性的数据类型来操作
3.匿名属性一般都用于结构体的嵌套定义
结构体的属性又是一个结构体
*/
/*
type Person struct {
int // 只有数据类型, 没有名称, 就是匿名属性
name string
}
//var per Person = Person{666, "msh"}
//fmt.Println(per)
var per Person
per.int = 666
per.name = "msh"
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}}
}
4、结构体嵌套
package main
import "fmt"
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{"msh", 33}, "zs", "老师"}
fmt.Println(tea)
fmt.Println(tea.name) // zs
fmt.Println(tea.Person.name) // msh
*/
// 第二种方式: 没有重名属性的情况
/*
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{"msh"}, "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) // msh
*/
// 第三种方式: 没有重名属性的情况
/*
type Object struct {
name string
}
type Person struct {
age int
}
type Student struct {
Object
Person
score float32
}
stu := Student{Object{"msh"}, 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"}, "msh",99.5}
fmt.Println(stu.name)
fmt.Println(stu.Object.name)
fmt.Println(stu.Person.name)
}
5、结构体匿名属性注意点
package main
import "fmt"
func main() {
/*
1.结构体的嵌套定义的注意点:
1.1结构体的属性类型不能是当前结构体的类型
1.2只有匿名属性才会向上查找, 非匿名属性不会向上查找
*/
//type Person struct {
// Person // 会报错, 不能自己搞自己
// name string
//}
//type Person struct {
// *Person // 不会报错, 链表
// name string
//}
type Person struct {
name string
}
type Student struct {
//Person // 匿名属性
per Person // 匿名属性
age int
}
stu := Student{Person{"msh"}, 18}
//fmt.Println(stu.per.name)
fmt.Println(stu.name)
}