结构体
Go语言中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,Go语言提供了一种自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体,英文名称struct。 也就是我们可以通过struct来定义自己的类型了。
package main
import "fmt"
func main() {
//结构体的定义
type person struct {
name string
age, height int
hobby []string
}
//就够提的实例化
var p1 person
fmt.Println(p1)
//结构体的初始化
var p = person{
name: "董立群",
age: 21,
height: 175,
hobby: []string{"吃", "喝", "玩", "乐"},
}
fmt.Println(p)
//结构体取值
fmt.Println(p.name)
fmt.Println(p.age)
fmt.Println(p.hobby)
//匿名结构体
var structpp struct {
name string
}
structpp.name = "郑凯健"
fmt.Println(structpp)
//指针结构体
var ppp = new(person)
ppp.name = "郭磊"
fmt.Println(ppp)
//go语言支持对指针结构体使用.来访问结构体的成员
fmt.Println(ppp.name)
//结构体的内存布局,结构体占用的是一块连续的内存
type test struct {
a int8
b int8
c int8
d int8
}
n := test{
1, 2, 3, 4,
}
fmt.Printf("n.a %p\n", &n.a)
fmt.Printf("n.b %p\n", &n.b)
fmt.Printf("n.c %p\n", &n.c)
fmt.Printf("n.d %p\n", &n.d)
//面试题
type student struct {
name string
age int
}
m := make(map[string]*student)
stus := []student{
{name: "小王子", age: 18},
{name: "娜扎", age: 23},
{name: "大王八", age: 9000},
}
//在这里,因为range是值拷贝,每一次循环都用的是stu这个变量,所以他的内存地址一直都没有变
//也就是说最后stu中剩下的只有数组遍历的最后一个拷贝“大王八”。m的每个值都是指向stu的内存地址
for _, stu := range stus {
m[stu.name] = &stu
}
fmt.Println(m)
for k, v := range m {
fmt.Println(k, "=>", v.name)
}
}
方法和接受者
Go语言中的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者(Receiver)。接收者的概念就类似于其他语言中的this或者 self。
指针接接收者
指针类型的接收者由一个结构体的指针组成,由于指针的特性,调用方法时修改接收者指针的任意成员变量,在方法结束后,修改都是有效的。这种方式就十分接近于其他语言中面向对象中的this或者self。 例如我们为Person添加一个SetAge方法,来修改实例变量的年龄。
package main
import "fmt"
type person struct {
name string
age int
}
//方法的定义格式
// func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
// 函数体
// }
func (p *person) fun() {
p.name = "dlq"
fmt.Println(p.name)
p.newAge(3)
}
func (p *person) newAge(i int) {
p.age = i
}
//给任意类型添加一个方法
type intt int
func (i intt) fu() {
}
func main() {
var p = &person{}
p.fun()
fmt.Println(p.age)
p.newAge(6)
fmt.Println(p.age)
//任意类型方法的调用
var i = intt(1)
i.fu()
//匿名结构体
type paa struct {
int
string
}
ppp := paa{
23,
"dlq",
}
fmt.Println(ppp)
//结构体的嵌套
//匿名结构体嵌套的情况下,不用先调用paa结构体再调用paa中的值,可以直接通过p1调用
//在结构体嵌套中,如果出现了嵌套结构体名字重复,那么就要指定具体的内嵌结构体字段名。
type person0 struct {
name string
age int
paa
}
var p1 = person0{
"dlq",
23,
paa{
23,
"dlq",
},
}
fmt.Println(p1.name)
fmt.Println(p1)
}
结构体模拟继承
package main
type person struct {
name string
age int
}
type dog struct {
name string
age int
person
}
func (p *person) fun() {
}
func (d *dog) funcc() {
}
func main() {
d := &dog{}
d.funcc()
d.fun()
}
结构体与json序列化
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Age int `json:"age"`
}
type person1 struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
p := &person{
"dlq",
32,
}
//序列化
jss, err := json.Marshal(p)
if err != nil {
fmt.Println("error")
return
}
fmt.Println(string(jss))
//反序列化
p1 := &person1{}
str := `{"name":"dlq","age":23}`
err1 := json.Unmarshal([]byte(str), p1)
if err1 != nil {
fmt.Println("error")
return
}
fmt.Println(p1)
}