前言
众所周知数组是存取同一类型的数据,要存储不同类型该怎么办呢,结构体由此而生,java,C语言中也都有结构体
结构体的定义和初始化
一般格式:
type 结构体名称 struct{
变量
变量
变量
}
初始化
按照变量的顺序提供,注意顺序不能乱,因为类型不一
p:= person{“Tom”,25}
加上变量名,可以任意顺序
p:=person{age:25,name:“Tom”}
new方式未设置类型,会赋予默认类型
p:=new(person)
p.age=24
一般通过点.操作符来访问结构体的每个字段
代码实例:
type Book struct {
title string
author string
id int
}
func main() {
var Book1 Book /* 声明 Book1 为 Book 类型 */
var Book2 Book /* 声明 Book2 为 Book 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "菜菜的涛"
Book1.id = 2671028219
/* book 2 描述 */
Book2.title = "java 教程"
Book2.author = "菜菜的涛"
Book2.id = 18236191608
/* 输出 Book1 信息 */
fmt.Printf( "Book1的标题是 : %s\n", Book1.title)
fmt.Printf( "Book1的作者是 : %s\n", Book1.author)
fmt.Printf( "Book1的id是 : %d\n", Book1.id)
/* 输出 Book2 信息 */
fmt.Printf( "Book2的标题是: %s\n", Book2.title)
fmt.Printf( "Book2的作者是 : %s\n", Book2.author)
fmt.Printf( "Book2的id是: %d\n", Book2.id)
}
Book1的标题是 : Go 语言
Book1的作者是 : 菜菜的涛
Book1的id是 : 2671028219
Book2的标题是: java 教程
Book2的作者是 : 菜菜的涛
Book2的id是: 18236191608
结构体指针
一般格式:
var 结构体指针 *结构体名称
结构体指针是一个指针变量,可以存储结构体变量的地址,如果要查看结构体指针,可以使用&符号
使用机构体指针访问结构体成员,使用“.”操作符
代码实例:
type Book struct {
title string
author string
id int
}
func printBook(book *Book) {
fmt.Printf("Book的标题为 : %s\n", book.title);
fmt.Printf("Book的作者为 : %s\n", book.author);
fmt.Printf("Book的id为 : %d\n", book.id);
}
func main() {
var Book1 Book
var Book2 Book
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "菜菜的涛"
Book1.id = 2671028219
/* book 2 描述 */
Book2.title = "java 教程"
Book2.author = "菜菜的涛"
Book2.id = 18236191608
/* 打印 Book1 信息 */
printBook(&Book1)
/* 打印 Book2 信息 */
printBook(&Book2)
}
Book1的标题是 : Go 语言
Book1的作者是 : 菜菜的涛
Book1的id是 : 2671028219
Book2的标题是: java 教程
Book2的作者是 : 菜菜的涛
Book2的id是: 18236191608
结构体嵌套
结构体匿名字段
可以用字段来创建结构体,这些字段中只包含一个没有字段名的类型,因此被称为匿名字段
type Person struct {
name string
age int
weight int
}
type Student struct {
Person // 默认Student就包含了Person的所有字段
speciality string
}
也可以这样
type Address struct {
city, state string
}
type Person struct {
name string
age int
address Address
}
而存在于结构体的匿名字段叫做提升字段
type Address struct {
city, state string
}
type Person struct {
name string
age int
Address
}
func main() {
var p Person
p.name = "菜菜的涛"
p.age = 19
p.Address = Address{
city: "新乡",
state: "红旗区",
}
fmt.Println("Name:", p.name)
fmt.Println("Age:", p.age)
fmt.Println("City:", p.city)
fmt.Println("State:", p.state)
}
Name: 菜菜的涛
Age: 19
City: 新乡
State: 红旗区
在go中区别公共私有的方式往往是根据变量名开头大小写,若为大写,则可以通过其他包去访问它,所以结构体中如果里面的变零有以大写字母开头的那么其他包是可以去访问的
结构体的比较
因为结构体是值类型,如果对应的字段相等,则称这两个结构体是相等的
type name struct {
oldName string
newName string
}
func main() {
name1 := name{"Jack", "Pop"}
name2 := name{"Jack", "POP"}
if name1 == name2 {
fmt.Println("name1和name2是相等的")
} else {
fmt.Println("name1和name2不相等")
}
name3 := name{oldName:"菜菜的涛", lastName:"无敌"}
name4 := name{}
name4.firstName = "Mavir"
if name3 == name4 {
fmt.Println("name3和name4是相等的")
} else {
fmt.Println("name3和name4不相等")
}
}
name1 and name2 are equal
name3 and name4 are not equal
如果结构体里包含的字段比较不了则结构体就无法比较,例如结构体包含的字段为map
同样结构体也可以作为参数在函数中传递,函数中也可以访问结构体中的任一变量
make与new
简单说说,make往往用于内建类型(map,slice和channel)的内存分配,new用于各种类型的内存分配,返回值为指针make返回的是一个有初始值的类型。
而对于slice,map和channel这三个之所以有所不同的原因是指向数据结构的引用在使用前必须被初始化,例如在一个切片未被初始化前,它的默认值就为nil,而map能初始化它内部的数据结构,从而可以填充适当的值