结构体struct的用法
import (
"fmt"
)
定义
结构体 首字母 大写是公有(public) 小写就是私有(private)
属性 首字母 大写是公有(public) 小写就是私有(private)
type person struct {
name string
sex string
age int
}
实例化结构体
//1.
var p person //实例化结构体
p.name = "王二"
p.age = 20
p.sex = "男"
fmt.Printf("值:%v 类型:%T\n",p,p) //值:{王二 男 20} 类型:demo.Person
fmt.Printf("详细值:%#v 类型:%T\n",p,p) //详细值:demo.Person{name:"王二", sex:"男", age:20} 类型:demo.Person
//2.new 实例结构体 在golang 中 支持对结构体指针直接使用.来访问结构体的成员 p2.name 其实底层是(*p).name
var p2 = new(person)
p2.name = "李四"
p2.sex = "男"
p2.age = 23
fmt.Printf("%#v--%T\n",p2,p2) //&demo.person{name:"李四", sex:"男", age:23}--*demo.person
//3.
var p3 = &person{}
p3.name = "六六"
p3.age = 30
p3.sex = "女"
fmt.Printf("%#v--%T\n",p3,p3)//&demo.person{name:"六六", sex:"女", age:30}--*demo.person
//4.
var p4 = person{
name:"七七",
age:34,
sex: "女",
}
fmt.Printf("%#v--%T\n",p4,p4)//demo.person{name:"七七", sex:"女", age:34}--demo.person
//5.
var p5 = &person{
name:"七七一",
age:34,
sex: "女",
}
fmt.Printf("%#v--%T\n",p5,p5)//&demo.person{name:"七七一", sex:"女", age:34}--*demo.person
//6.
var p6 = &person{
name:"李一",
}
fmt.Printf("%#v--%T\n",p6,p6)//&demo.person{name:"李一", sex:"", age:0}--*demo.person
//7.
var p7 = &person{ //属性数据要跟结构体定义一致
"王子",
"男",
20,
}
fmt.Printf("%#v--%T\n",p7,p7)//&demo.person{name:"王子", sex:"男", age:20}--*demo.person
结构体方法
type person struct {
name string
sex string
age int
}
//结构体方法
//值类型接受者
func (p person)printInfo() {
fmt.Println(p)
}
//指针类型接收者
func (p *person) setInfo(name string,age int) {
p.age = age
p.name = name
}
func TestStruct(t *testing.T) {
var p8 = person{
name:"天一",
sex:"男",
age: 20,
}
p8.printInfo()//{天一 男 20}
p8.setInfo("网网",30)
p8.printInfo()//{网网 男 30}
}
自定义类型 添加方法
//注意:非本地类型不能定义方法,也就是说我们不能给别的包的类型定义方法
type MyString string
func (s MyString)PrintMyString() {
fmt.Println(s)
}
func TestMyString(t *testing.T) {
var str MyString = "sss"
str.PrintMyString() //sss
}
结构体的匿名字段
- 结构体允许其成员字段在声明时没有字段 名而只有类型,这种没有名字的字段就称为匿名字段
- 匿名字段默认采用类型名作为字段名,结构体要求字段 名称必须唯一,因此一个结构体中同种类型的匿名字段只能有一个
type info struct {
string
int32
}
func TestStructType(t *testing.T) {
var message = info{
"hello",
30,
}
fmt.Println(message) //{hello 30}
}
结构体字段类型
- 结构体的字段类型可以是:基本数据类型,也可以是切片、Map 以及结构体
- 如果结构体的字段类型是:指针、slice、 和Map的默认值都是nil,即还没有分配空间
- 如果需要使用这样的字段,需要先make 分配空间 才能使用
type School struct {
Name string
SchoolCourse []string
SchoolSize int
SchoolType map[string]string
}
func TestSchoolStruct(t *testing.T) {
var s School
s.Name = "幼儿园"
s.SchoolType = make(map[string]string)
s.SchoolType["小班"] = "小1班,小2班"
s.SchoolType["中班"] = "中1班,中2班"
s.SchoolType["大班"] = "大1班,大2班"
s.SchoolSize = 3500
s.SchoolCourse = make([]string, 4, 4)
s.SchoolCourse[0] = "画画"
s.SchoolCourse[1] = "拼音"
s.SchoolCourse[2] = "运动"
s.SchoolCourse[3] = "音乐"
fmt.Println(s) //{幼儿园 [画画 拼音 运动 音乐] 3500 map[中班:中1班,中2班 大班:大1班,大2班 小班:小1班,小2班]}
}
结构体嵌套
- 一个结构体中可以嵌套包含另一个结构体
- 嵌套结构体内部可能存在相同的字段名。这个时候为了避免歧义需要指定具体的内嵌结构体的字段。
type User struct {
Name string
Age int
Zip int
Address
Email
}
type Address struct {
City string
Street string
AddTime int
}
type Email struct {
EmailAddress string
AddTime int
}
func TestStructNest(t *testing.T) {
var u User
u.Name = "王二"
u.Age = 30
u.Zip = 200000
u.Address.City = "上海"
u.Street = "xxx路xxx号" //当访问结构体成员时会先在结构体中查找该字段 ,找不到再去匿名结构体中查找
u.Address.AddTime = 123123213
u.Email.AddTime = 321321321 //u.AddTime = 321321321 error 嵌套多个结构体中同名的字段需要加个结构体名
fmt.Println(u) //{王二 30 200000 {上海 xxx路xxx号 123123213} { 321321321}}
}
结构体的继承
父结构体
type Animal struct {
Name string
}
func (a Animal) Play() {
fmt.Printf("%v 在玩耍\n", a.Name)
}
子结构体
type Pig struct {
Age int
Animal //嵌套,继承
}
func (p Pig) Speak() {
fmt.Printf("%v 在讲话\n", p.Name)
}
一个结构体中可以嵌套结构体指针
type Dog struct {
Age int
*Animal //嵌套,继承,指针
}
func (d Dog) Run() {
fmt.Printf("%v 在运动\n", d.Name)
}
func TestStructExtend(t *testing.T) {
/*var p Pig
p.Name = "小猪佩奇"
p.Age = 4*/
var p = Pig{
Age: 4,
Animal: Animal{
"小猪佩奇",
},
}
p.Play() //小猪佩奇 在玩耍
p.Speak() //小猪佩奇 在讲话
var d = Dog{
Age: 4,
Animal: &Animal{
"小狗丹尼",
},
}
d.Play() //小狗丹尼 在玩耍
d.Run() //小狗丹尼 在讲话
}