结构体
结构体介绍
数组可以存储同一类型的数据,而结构体是由任意类型构成的集合.结构体支持自定义类型,或叫定制类型.结构体的成员属性或叫字段.结构体的定义知识一种内存布局的描述,只有在实例化构造体后才会分配内存.所以在使用构造体之前需要先实例化.
定义结构体
使用type
将各种类型定义为自定义类型,struct{}
表示机构体类型.且结构体中的字段名是必须唯一,不可重复哦~
type 类型名 struct {
字段1 类型
字段2 类型
}
例如定义一个博客的构造题,包括整型的博客id和字数,以及字符类型的作者和标题.
// 定义blog构造题
type Blog struct{
// 成员变量id,字数为int.作者和标题为string
id,number int
writer,title string
}
实例化结构体
基本实例化:使用var声明结构体.var 实例名称 结构体
.例如
// 定义blog构造体
type Blog struct{
// 成员变量id,字数为int.作者和标题为string
id,number int
writer,title string
}
func main() {
var myBlog Blog
fmt.Println(myBlog)
}
// 打印结果
{0 0 }
指针类型:使用new(构造体名)
进行实例化,实例化后会新城指针类型的结构体.
// 定义blog构造体
type Blog struct{
// 成员变量id,字数为int.作者和标题为string
id,number int
writer,title string
}
func main() {
// myblog属于指针
myBlog := new(Blog)
fmt.Println(myBlog)
}
// 打印结果
&{0 0 }
取地址实例化:对结构体使用&
取地址相当于对该类型进行一次new的实例化操作
// 定义blog构造体
type Blog struct{
// 成员变量id,字数为int.作者和标题为string
id,number int
writer,title string
}
func main() {
myBlog := &Blog{}
fmt.Println(myBlog)
}
// 打印结果
&{0 0 }
取地址实例化结构体是比较常见的,可以使用工厂模式进行封装.如下
// 声明结构体
type Myblog struct {
Id,Number int
Writer,Title string
}
// 工厂函数,返回结构体的指针
func createBlog(id, number int, writer, title string) *Myblog {
// 通过&结构体{}实例化结构体并返回
return &Myblog{Id: id, Number: number, Writer: writer, Title: title}
}
func main() {
// 调用工厂函数,通过工厂函数实例化结构体
blog1 := createBlog(1, 1234, "QvBiLam", "为什么要学Go呢?")
blog2 := createBlog(2, 1334, "QvBiLam", "为什么要学PHP呢?")
fmt.Print(blog1,blog2)
}
初始化成员变量
健值初始化:按照成员变量对应的值进行初始化.
type Myblog struct {
Id, Number int
Writer, Title string
}
func main() {
blog1 := Myblog{
Writer: "QvBiLam",
Title: "Go好难呀",
}
fmt.Printf("文章名称:%s,文章作者:%s", blog1.Title, blog1.Writer)
}
值顺序初始化:按照结构体内成员变量的顺序进行初始化.
type Myblog struct {
Id,Number int
Writer,Title string
}
func main() {
blog2 := Myblog{2,123,"QvBiLam","我还是喜欢php"}
fmt.Printf("文章名称:%s,文章作者:%s",blog1.Title,blog1.Writer)
}
成员变量也可以是结构体,为了方便理解,在这里进行演示,如下家庭的结构体.成员变量有name,child,其中child是指针又指向了家庭的结构:通过初始化成员属性可以更好的理解:
type Family struct {
Name string
Child *Family
}
func main() {
myFamily := Family{
Name:"爸爸",
Child:&Family{
Name: "*毅",
Child: &Family{
Name: "赵**",
},
},
}
// 获取家庭孩子的孩子的姓名
mySon:= myFamily.Child.Child.Name
fmt.Println(mySon)
}
方法
方法介绍
在函数声明时,在函数名放上一个变量,那么它就是一个方法.新增的变量会讲该函数附加到这种类型上,相当于为这种类型定义了一个独占的方法.其中
注意:
- 接收者只能使用
type
定义的类型,例如自定义类型,结构体. - 同一个接受者的方法名不能重复,如果是结构体,方法名不能和字段重复.
- 方法为值接受者,如需要修改则使用指针类型
方法的使用
// 定义结构体
type blog struct{}
// 定义方法
func (b blog) Print(){
fmt.Print("Go的方法")
}
func main() {
//实例化结构体
b := blog{}
// 点用结构体的方法
b.Print()
}
例如下面示例对文章的浏览量进行自增.
// 定义结构体
type Blog struct{
title string // 标题
pageview int //浏览数
}
// 定义增加浏览量方法
func (b Blog) pvAdd(){
b.pageview += 1
}
// 定义打印方法
func (b Blog) Print(){
fmt.Printf("标题:%s, 浏览量:%d \n",b.title,b.pageview)
}
func main() {
//实例化结构体
b := Blog{"Golang--方法",0}
b.pvAdd()
b.Print()
b.pvAdd()
b.Print()
}
虽然调用了两次pvAdd
方法但是打印的结果一直都是0.正如前面所说如果需要通过方法对结构体的成员变量进行修改需要引用指针类型.修改如下:
// 定义增加浏览量方法
// 为Blog结构体添加* 变为指针
func (b *Blog) pvAdd(){
b.pageview += 1
}
完整代码如下:
package main
import "fmt"
// 定义结构体
type Blog struct{
title string // 标题
pageview int //浏览数
}
// 定义增加浏览量方法
func (b *Blog) pvAdd(){
b.pageview += 1
}
// 定义打印方法
func (b Blog) Print(){
fmt.Printf("标题:%s, 浏览量:%d \n",b.title,b.pageview)
}
func main() {
//实例化结构体
b := Blog{"Golang--方法",0}
b.pvAdd()
b.Print()
b.pvAdd()
b.Print()
}
气死我了。
赵**