1、结构体介绍
- 为什么要有结构体?
数组只能保存同一种类型的数据,当需要记录多种不同类型的数据,并聚集在一起用来描述复杂的实体时,怎么办?
结构体就是用于解决这个问题的,结构体是由一系列具有相同类型或不同类型的数据构成的数据集合,方便容量任意类型的数据
结构体的目的就是把数据聚集在一起,以便能够更加便捷的操作这些数据
结构体是由一些列属性组成的复合数据类型,每个属性都具有名称、类型和值,结构体将属性组合在一起进行由程序进行处理
- 结构体和类的概念
gogo
一个成熟的类,具备成员变量和成员函数,结构体本身就有成员变量,再给他绑定上成员函数,就可以了
- 结构体单例绑定
sayHello()
*
type People struct {
name string
}
func (p People) toString() {
fmt.Println(p.name)
fmt.Printf("p的地址 %p \n", &p)
}
func (p *People) sayHello() {
fmt.Printf("Hello %v \n", p.name)
fmt.Printf("*P的地址 %p \n", p)
}
2、结构体的定义
structtypestruct
结构体的定义格式如下
type 类型名 struct {
字段1 类型1
字段2 类型2
//...
}
以上各个部分的说明如下
- 类型名:标识自定义结构体的名称,在同一个包内不能包含重复的类型名
- struct{}:表示结构体类型,type类型名struct{}可以被理解为将struct{}结构体定义为类型名的类型
- 字段1、字段2......:表示结构体字段名。结构体中的字段名必须唯一
- 类型1、类型2......:表示结构体各个字段的类型,结构体中的字段可以是任意类型:string、int、float;复合类型:map、slice、channel、struct
在定义结构体时可以为结构体指定结构体名(命名结构体),用于后续声明结构体变量使用
type struct_variable_type struct {
member definition
member definition
...
member definition
}
例如 用于描述一个人的特征
如果单独使用变量描述应该如何描述?
没有结构体
var (
name string
age int
gender string
weight uint
favoriteColor []string
)
使用结构体
type Person struct {
Name string
Age int
Gender string
Weight uint
FavoriteColor []string
}
type User struct {
ID int
Name string
Birthday string
Addr string
Tel string
Remark string
}
如果某几个字段类型相同,可以缩写在同一行:
type Person struct {
Name, City string
Age int
}
可以看出结构体就像一个容器,这个容器里面装什么自己定义,这也是结构体的特点: 自定义化的程度很高,使用灵活
一旦定义了结构体类型,则它就能用于变量的声明,语法格式如下
variable_name := struct_variable_type {value1, value2,...}
或
variable_name := struct_variable_type {key1: value1, key2: value2,...}
Book
package main
import "fmt"
type Book struct {
title string
author string
subject string
press string
}
func main() {
// 创建一个新的结构体
fmt.Println(Book{"Go基础", "ssgeek", "Go语言", "Go语言教程"})
// 也可以使用 key => value 格式
fmt.Println(Book{title: "Go基础", author: "ssgeek", subject: "Go语言", press: "Go语言教程"})
// 忽略的字段为 0 或 空
fmt.Println(Book{title: "Go基础", author: "ssgeek"})
}
3、构造结构体实例
structstructClassObject
对应的结构体定义
type Car struct {
Color string // 颜色
Brand string // 品牌
Model string // 型号
}
var car Car // 初始化一个Car实例, car就代表是一辆具体的车(Object)
carCarCarColorBrandModelcar
struct00int0stringnil
var car Car
fmt.Printf("%+v", car) // {Color: Brand: Model:}
也可以在声明的时候直接为成员变量赋值,通常把这个过程称之为构造结构体的实例, 语法如下:
// 使用{k:v, k:v}这种方式来为结构体的成员赋值
TypeName{filed1: value1, filed2: value2, ...}
// 为了书写美观, 通常都把每一个k:v 独立写在一行,比如:
TypeName{
file1: value1,
file2: value2,
...
}
Car
// 为了书写的简洁,采用简单声明的方式, 就像 a := 10 <---> var a int; a = 10
//
var car Car
fmt.Printf("%+v\n", car)
car = Car{ // 当然也可以不然声明car的类型, 直接使用简短声明: car := Car{...}
Color: "yellow", // 黄色
Brand: "ford", // 福特
Model: "yema", //
}
fmt.Printf("%+v\n", car) // {Color:yellow Brand:ford Model:yema}
// 注意,上面最后一个逗号","不能省略,Go会报错,这个逗号有助于去扩展这个结构
4、声明与初始化
声明结构体变量只需要定义变量类型为结构体名,变量中的每个属性被初始化为对应类型的零值
nil
var struct_name struct_type
使用结构体创建的变量叫做对应结构体的实例或者对象
- 只声明不初始化
person
// 只声明
var person Person
var me User
fmt.Printf("%T\n", me) // main.User
可以看到声明后的结构体的所有属性都是初始值
varfalse
var person Person
fmt.Printf("%+v\n", person)
// {Name: Age:0 Gender: Weight:0 FavoriteColor:[]}
var me3 User = User{}
fmt.Println(me3) // {0 0001-01-01 00:00:00 +0000 UTC }
-
声明并初始化
使用字面量初始化结构体值对象
var person Person = Person{
Name: "andy",
Age: 66,
Gender: "male",
Weight: 120,
FavoriteColor: []string{"red", "blue"},
}
fmt.Printf("%+v\n", person)
// {Name:andy Age:66 Gender:male Weight:120 FavoriteColor:[red blue]}
fmt.Printf("%p\n", &person.Name) // 0xc0000ce080 地址相邻
fmt.Printf("%p\n", &person.Age) // 0xc0000ce090 地址相邻
var me2 User = User{
1,
"geek",
time.Now().Format("2006-01-02"),
"北京市",
"15588888888",
"这是备注2",
}
fmt.Printf("%v\n", me2) // {1 geek 2021-08-10 北京市 155888888888 这是备注2}
可以在函数外部使用,可以用来声明初始化全局变量
Go
- 使用短变量声明
// 变量 := 结构体{赋值}
func TestPerson32(t *testing.T) {
p3 := Person3{
Name: "ssgeek",
Age: 24,
}
fmt.Println(p3)
}
- 通过属性名
// 通过属性名指定,可以省略、无序
var me4 User = User{ID:1, Name: "geek", Birthday: time.Now().Format("2006-01-02"), Addr: "北京市", Tel: "15588888888"}
fmt.Println(me4)
- 使用new函数进行初始化结构体指针对象
var me5 *User = new(User)
fmt.Printf("%T, %#v, %#v\n", me5, me5, *me5)
- 使用指针初始化
var me6 *User
fmt.Printf("%T\n", me6) // *main.User
fmt.Printf("%#v\n", me6) // (*main.User)(nil)
var me7 = &User{ID: 2, Name: "geek"}
fmt.Printf("%T\n", me7) // *main.User
5、属性的访问和修改
通过结构体对象名.属性名的方式来访问和修改对象的属性值
可以通过结构体指针对象的点操作直接对对象的属性值进行访问和修改
// 语法:结构体.成员名
fmt.Println((&person).Name) // andy
fmt.Println(person.Name) // andy
person.Age = 20
fmt.Println(person.Age) // 20
golangselector
func main() {
p1 := Person{
Name: "geek",
Age: 9000,
}
fmt.Println(p1.Name, p1.Age)
p1.Age += 1
fmt.Println(p1.Name, p1.Age)
}
See you ~