知识点梳理
- 结构体可以使用
new
关键字对结构体进行实例化,得到的是结构体的地址。var p2 = new(person) p2.name = "小王子" p2.age = 28 p2.city = "上海" fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"小王子", city:"上海", age:28}
- 结构体可使用
&
对结构体进行取地址操作相当于对该结构体类型进行了一次new
实例化操作。p3 := &person{} fmt.Printf("%T\n", p3) //*main.person fmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"", city:"", age:0} p3.name = "七米" p3.age = 30 p3.city = "成都" fmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"七米", city:"成都", age:30}
- 没有初始化的结构体,其成员变量都是对应其类型的零值。
type person struct { name string city string age int8 } func main() { var p4 person fmt.Printf("p4=%#v\n", p4) //p4=main.person{name:"", city:"", age:0} }
- 结构体的方法中值类型的接收者时,Go语言会在代码运行时将接收者的值复制一份。在值类型接收者的方法中可以获取接收者的成员值,但修改操作只是针对副本,无法修改接收者变量本身。
// SetAge2 设置p的年龄 // 使用值接收者 func (p Person) SetAge2(newAge int8) { p.age = newAge } func main() { p1 := NewPerson("小王子", 25) p1.Dream() fmt.Println(p1.age) // 25 p1.SetAge2(30) // (*p1).SetAge2(30) fmt.Println(p1.age) // 25 }
- 结构体占用一块连续的内存。
-
Go语言中支持对结构体指针直接使用
.
来访问结构体的成员。 -
在定义一些临时数据结构等场景下还可以使用匿名结构体。
package main import ( "fmt" ) func main() { var user struct{Name string; Age int} user.Name = "小王子" user.Age = 18 fmt.Printf("%#v\n", user) }
rune
和byte
类型就是int32、uint8类型别名type byte = uint8 type rune = int32
- 自定义类型关键字
type
//类型定义 type NewInt int //类型别名 type MyInt = int
- go 值类型包括 : 所有
整型
,所有浮点型
,bool型
,string型
,数组
和struct类型
值类型的特点是变量直接存储值,内存通常在 栈(stack) 中分配 -
go 引用类型包括:
指针
,slice
,map
,chan
,interface
引用类型的特点,变量存储的是一个地址,这个地址对应的空间才真正存储的数据,内存分配通常在 堆(heap) 上分配,当没有任何变量引用这个地址的时候,该地址对应的数据空间会被GC回收 -
Go语言提倡面向接口编程。实现接口中的所有方法,就实现了这个接口。
// 定义接口 type Mover interface { move() } // Sayer 接口 type Sayer interface { say() } // 小狗结构体 type dog struct {} // 小狗结构体的移动方法 func (d dog) move() { fmt.Println("狗会动") } // 实现Sayer接口 func (d dog) say() { fmt.Printf("%s会叫汪汪汪\n", d.name) } // 调用 func main() { // x 变量接口 var y Mover var x Sayer var wangcai = dog{} // 旺财是dog类型 x = wangcai // x可以接收dog类型 var fugui = &dog{} // 富贵是*dog类型 x = fugui // x可以接收*dog类型 x.say() y = wangcai y.move() }
-
切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)。
-
要检查切片是否为空,请始终使用
len(s) == 0
来判断,而不应该使用s == nil
来判断。 -
切片之间是不能比较的,我们不能使用
==
操作符来判断两个切片是否含有全部相等元素。