一、go sturct类型
1、值类型
2、struct名字不能与包名相
3、结构体指针与结构体变量都可以通过.
访问成员,这是一种语法糖。
4、struct初始化示例
type Point struct {
X int
Y int
}
func test1() {
// (1)先声明变量,再给成员赋值
var p1 Point
p1.X = 10
p1.Y = 5
// (2)直接初始化
p2 := Point{
X: 10, //允许只初始化部分成员
}
// (3)初始化指针类型
var p3 *Point = &Point{}
// (4)初始化指针类型,并赋值
p4 := &Point{
X: 10,
Y: 5,
}
// (5)使用new构造指针
var p5 *Point = new(Point)
p5.X = 10
p5.Y = 5
}
二、go内存布局
1、占用一段连续的内存空间
func test2() {
type Array struct {
A, B, C, D int
}
arr := Array{
A: 1, B: 2, C: 3, D: 4,
}
fmt.Printf("the address of A:%p\n", &arr.A)
fmt.Printf("the address of B:%p\n", &arr.B)
fmt.Printf("the address of C:%p\n", &arr.C)
fmt.Printf("the address of D:%p\n", &arr.D)
}
/*
the address of A:0xc00011c120
the address of B:0xc00011c128
the address of C:0xc00011c130
the address of D:0xc00011c138
*/
2、没有构造函数,必要时需自己实现
func creatPoint(x, y int) Point {
return Point{
X: x,
Y: y,
}
}
func test3() {
fmt.Printf("the new Point is %#v\n", creatPoint(1, 2))
}
三、匿名字段
匿名字段就是只有类型,没有成员名,go会把类型默认为字段名。
1、匿名字段的访问方式
type User struct {
name string
age int
float32
}
func test4() {
var li User
li.float32 = 9.9
fmt.Printf("the value of li:%#v\n", li)
}
2、结构体中可以嵌套匿名结构体,结构体中字段查找的优先级:由上至下,优先使用结构体中的成员,再去找匿名结构体中的字段。
type Address struct {
Location string
CreatTime string
}
type User struct {
Name string
Age int
CreatTime string
Address
}
func test5() {
var li User
li.CreatTime = "2020"
fmt.Printf("the value of li:%#v\n", li)
}
/*
the value of li:main.User{Name:"", Age:0, CreatTime:"2020", Address:main.Address{Location:"", CreatTime:""}}
*/
3、解决命名冲突的方法:如果有多个匿名结构体成员中包含了相同名字的字段,访问时,必须指定访问哪个匿名结构体中的字段,否则会编译报错。解决冲突的办法就是通过指定匿名结构体的类型。
type Address struct {
Location string
CreatTime string
}
type Email struct {
Value string
CreatTime string
}
type User struct {
Name string
Age int
Address
Email
}
func test6() {
var li User
li.Email.CreatTime = "2020"
//li.CreatTime = "2020" //Error:ambiguous selector li.CreatTime
fmt.Printf("the value of li:%#v\n", li)
}
/*
the value of li:main.User{Name:"", Age:0, Address:main.Address{Location:"", CreatTime:""}, Email:main.Email{Value:"", CreatTime:"2020"}}
*/
四、访问权限
成员命名大写开头表示公有,小宇表示私有。
五、结构体tag
tag是结构体的元信息,可以在运⾏的时候通过反射的机制读取出来。字段类型后⾯,以反引号括起来的
key-value
结构的字符串,多个tag
用逗号展开。
type User struct {
Name string `json:"value Name"`
Age int
Address
Email
}
六、面向对象之定义方法
1、声明函数前设置一个方法的接收者(结构体类型,也可是指针类型),调用方法时传一个方法的接收者(最好传指针,避免值传递)
2、可以为任意类型增加方法。
type Integer int
func (i Integer) print() {
fmt.Println(i)
}
func test7() {
var a Integer = 10
a.print()
}
3、go中使用组合
的方式实现继承。
type Animal struct {
name string
age int
}
func (this *Animal) talk() {
fmt.Printf("I am %v\n", this.name)
}
type Dog struct {
family string
*Animal
}
func (this *Dog) run() {
fmt.Printf("my faimly is %v\n", this.family)
}
func test8() {
d := &Dog{
family: "Hong",
Animal: &Animal{
name: "xiaohei",
age: 10,
},
}
d.talk()
d.run()
}
七、结构体序列化与反序列化
示例:
func test9() {
p1 := &Point{
X: 10,
Y: 5,
}
pJson, err := json.Marshal(p1)
if err == nil {
fmt.Printf("Serialization: %v\n", string(pJson))
}
var s string = `{"X":10,"Y":5}`
var p2 *Point = &Point{}
err = json.Unmarshal([]byte(s), p2)
if err == nil {
fmt.Printf("the value of p2:%#v\n", p2)
}
}
八、匿名结构体初始化
示例:
func test10() {
type cat struct {
Name string
Color string
Age int
Home struct {
Adderess string
PostCode int
}
}
ins := cat{
Name: "Tom",
Color: "Dark",
Age: 5,
Home: struct{
Adderess string
PostCode int
}{
"England",
1024,
},
}
}