一、快速入门
1、声明结构体
type 结构体名称 struct{
field1 type
field2 type
}
例如
type Person struct {
Name string
Age int
Scores [5]float64
ptr *int
slice []int
map1 map[string]string
}
2、创建结构体变量和访问结构体
(1)
var person Person
(2)
var person Person = {“mary”,20}
(3)
var p3 *Person = new(Person)
//此时p3是一个指针,因此标准的给字段赋值方式如下:
(*p3).Name = "smith"
(*p3).Age = 30
//以上写法等价于(go设计时,在底层会对这种写法处理,加上取值运算)
p3.Name = "smith"
p3.Age = 30
(4)
var person *Person = &Person{}
(*person).Name = "scott"
(*person).Age = 88
3、如果结构体名称首字母大写,那么该结构体类型可以在其他包使用
如果字段(filed、属性)首字母大写,那么可以在其他包引用
4、字段(属性)一般是基本数据类型、数组,也可以是引用类型
如果结构体的字段类型是: 指针、slice、和map 的零值都是nil,即还没有分配空间,如果需要使用slice,map,就要先 make 再使用
package main
import (
"fmt"
_ "fmt"
)
type Person struct {
Name string
Age int
Scores [5]float64
ptr *int
slice []int
map1 map[string]string
}
func main() {
//定义结构体
var p1 Person
fmt.Print(p1,"\n")
//slice
p1.slice = make([]int,10)
p1.slice[0]=100
//map
p1.map1 = make(map[string]string)
p1.map1["key1"] = "tom"
fmt.Print(p1,"\n")
}
5、不同结构体的字段是独立的,互不影响,修改一个不会影响另外一个
6、养猫问题
package main
import (
"fmt"
_ "fmt"
)
type Cat struct {
Name string
Age string
Color string
}
func main() {
var cat1 Cat
fmt.Print(cat1,"\n") //结构体是值类型,声明即创建
cat1.Name = "小黑"
cat1.Age = "10"
cat1.Color = "black"
fmt.Print(cat1,"\n")
}
二、结构体和结构体变量(实例)的区别和联系
1、结构体是自定义的数据类型,代表一类事务
2、结构体变量(实例)是具体的,实际的,代表一个具体变量
三、结构体在内存中的布局
1、结构体变量是值类型
2、内存图
四、结构体注意事项和细节
1、结构体的所有字段在内存中是连续的
package main
import "fmt"
type Point struct {
x int
y int
}
type Rect struct {
leftUp, rightup Point
}
func main() {
r1 := Rect{Point{1,2},Point{3,4},}
fmt.Printf("r1.letf.x 地址 %p,\nr1.letf.y 地址 %p,\nr1.right.x 地址 %p,\nr1.right.y 地址 %p\n",&r1.leftUp.x,
&r1.leftUp.y, &r1.rightup.x,&r1.rightup.y)
}
2、指针类型时,r2 两个Point类型,这两个Point类型的本身地址连续,但是指向地址一般不连续
package main
import "fmt"
type Point struct {
x int
y int
}
type Rect2 struct {
leftUp, rightup *Point
}
func main() {
//指针类型时
//r2 两个*Point类型,这两个*Point类型的本身地址连续,但是指向地址一般不连续
r2 :=Rect2{&Point{1,2},&Point{3,4}}
fmt.Printf("本身地址 r2.letf地址 %p,r2.right地址 %p\n",&r2.leftUp,&r2.rightup)
fmt.Printf("指向地址 r2.letf地址 %p,r2.right地址 %p",r2.leftUp,r2.rightup)
}
3、结构体是用户自己单独定义的类型,和其他类型进行转化是需要有完全相同的字段名(名字、个数和类型)即强制转换
type A truct{
Name int
}
type B truct{
Name int
}
func main(){
var a A
var b B
b = A(b)
}
4、struct 的每个字段上可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和反序列化。即json
package main
import "fmt"
import "encoding/json"
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Skill string `json:"skill"`
}
func main() {
//序列化 tag
monster :=Monster{"牛魔王",100,"芭蕉扇"}
jsonmonster ,err:=json.Marshal(monster)
if err != nil{
fmt.Print("错误")
}else {
fmt.Print(string(jsonmonster))
}
}