【Go】结构体,方法,接口
结构体
- Go语言是静态类型的语言,编译器需要在编译的时候知道每一个值的类型
- 提前知道值的类型,可以合理的保存。有助于减少内存异常和Bug。
- 一般需要知道:分配多少内存给这个值,这段内存表示什么。
定义与声明
1 | package main |
自定义类型
1 | type Duration int64 |
这个Duration是真是存在的一个类型,和int64是两个独立的类型,不能互相赋值
类型别名
1 | type rune = int32 |
类型别名,仅仅是存在于编码阶段,实际运行的时候还是原来的类型,提高可读性。
匿名结构体
1 |
|
一般就是临时使用,没有复用
指针类型结构体
1 | func main() { |
构造函数
- 结构体是指针类型的,但是如果指针类型比较复杂的话,值拷贝性能开销会比较大,所以构造函数返回值一般是结构体指针类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main(){
s :=newStudent(i,"mutong")
fmt.Println(s)
}
//构造函数
func newStudent(id int,name string) *student{
return &student{
Id: id,
Name: name,
}
}
序列化与反序列化
大写表示公开
小写表示私有
json.Marshal(c1)
序列化json.Unmarshal(c1)
反序列化1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56package main
import (
"encoding/json"
"fmt"
)
// 如果一个Go语言中定义的标识符是首字母大写的,那么就是对外可见的
// 如果一个结构体中的字段名首字母是答大写的,那么该自负就是对外可见的
func main() {
c1 := Class{
Title: "重点班",
Student: make([]student,0,20),
}
for i:= 0 ; i < 10; i++ {
s :=newStudent(i,"mutong")
c1.Student = append(c1.Student,s)
}
data, err := json.Marshal(c1)
if err != nil{
fmt.Println(err)
}else {
fmt.Printf("%s\n",data)
}
//JSON反序列化:JSON格式的字符串-->结构体
str := `{"Title":"101","Students":[{"ID":0,"Name":"stu00"},{"ID":1,"Name":"stu01"}]}`
var c2 Class
err = json.Unmarshal([]byte(str), &c2)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%#v\n", c2)
}
//构造函数
func newStudent(id int,name string)student{
return student{
Id: id,
Name: name,
}
}
type student struct {
Id int
Name string
}
//结构体嵌套
type Class struct {
Title string
Student []student
}几个注意:
- 空结构体是不占用空间的
- 构造
方法
- 方法能够给用户定义的类型增加新的行为,方法实际上也为函数,只不过,在声明的时候在关键字
func
和 方法名之间添加了一个参数 - 方法属于特定的类型,因为方法又一个接收者变量,只能有这个接收者变量才能调用。
- 函数不属于任何类型,可以直接调用。
- Go语言里面方法有两种类型的接收者:值接收者 和 指针类型接收者。
- 如果需要给这个类型创建一个新值,就使用值接收者。如果需要修改类型里面的一个值,就使用指针接收者。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package main
import "fmt"
func main(){
mutong := person{
name: "mutong",
age: 20,
}
mutong.notify()
mutong.changeAge(3)
fmt.Println(mutong)
//输出:
//Print person`s name :mutong
//{mutong 3 }
}
//普通方法
func (p person) notify(){
fmt.Println("Print person`s name :" + p.name)
}
//想要修改一个类型里面的值。需要使用指针接收者的方法
func (p *person) changeAge(age int){
p.age = age
}
接口
接口的定义
- 定义了一个接口之后,一定会有一个函数用接口类型做参数。
- 也一定又一个方法实现了接口里面的方法,方法的参数是一个用户自定义的类型。
1
2
3
4
5type 接口类型 interface {
方法1(参数列表 ) 返回值
方法2(参数列表 ) 返回值
...
}
1 | package main |