结构体
定义结构体
Go语言中通过关键字type定义自定义类型,结构体定义需要使用type和struct关键字,具体定义格式如下:
type 结构体名 struct {
成员变量1 类型1
成员变量2 类型2
成员变量3 类型3
...
}
注意:
- 结构体名:同一个包内结构体名不可以重复。
- 成员名:同一个结构体内,成员名不能重复。
- 类型1、类型2…:表示结构体成员变量的类型。
- 同类型的成员名可以写在同一行。
- 当结构体、方法名或变量名的首字母为大写时(可被导出),就可以在当前包外进行访问。
例如:
type Book struct {
title string
author string
num int
id int
}
实例化结构体
一个结构体在定义完成后才能进行。结构体实例化时,会真正地分配内存。因此必须在定义结构体并实例化后才能使用结构体的字段。Go语言实例化结构体主要有以下三种方式:
- 标准实例化
- new函数实例化
- 取地址实例化
标准实例化
var 结构化实例 结构体类型
例如:
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
func main() {
var book Book
fmt.Println(book)
}
new函数实例化
- new函数可对结构体进行实例化,实例化完成后会返回结构体的指针类型
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
func main() {
book := new(Book)
fmt.Println(book)
}
取地址实例化
- 取地址实例化与使用new函数进行实例化类似,返回的是结构体指针类型。取地址实例化格式如下:
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
func main() {
book := &Book{}
fmt.Println(book)
}
访问成员
结构体实例化后,可以通过“.”来访问结构体成员变量,对成员变量进行赋值或修改。
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
func main() {
book := &Book{}
book.title= "Go语言"
book.author= "Tom"
book.num= 20
book.id= 123
fmt.Println("title:",book.title)
fmt.Println("author:",book.author)
fmt.Println("num:",book.num)
fmt.Println("id:",book.id)
}
初始化结构体
键值对格式初始化
结构体实例 := 结构体类型{
成员变量1: 值1,
成员变量2: 值2,
成员变量3: 值3,
...
}
这种类型的初始化类似于对map数据类型的初始化操作,键和值之间以冒号分隔,键值对之间以逗号分隔。
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
func main() {
book := &Book{
title: "Go语言",
author: "Tom",
num: 20,
id: 123,
}
fmt.Println("title:",book.title)
fmt.Println("author:",book.author)
fmt.Println("num:",book.num)
fmt.Println("id:",book.id)
}
列表格式初始化
结构体实例 := 结构体类型{
值1,
值2,
值2,
}
注意:
- 使用这种方式初始化结构体必须初始化所有的成员变量。
- 值得填充顺序必须和结构体成员变量声明的顺序保持一致。
- 该方式与键值对的初始化方式不能混用。
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
func main() {
book := &Book{
"Go语言",
"Tom",
20,
123,
}
fmt.Println("title:",book.title)
fmt.Println("author:",book.author)
fmt.Println("num:",book.num)
fmt.Println("id:",book.id)
}
结构体方法
Go语言中,一个方法就是一个包含了接收者的函数。对于结构体方法,接收者可以是结构体类型的值或者指针。
指针类型接收者
当接收者类型为指针时,可以通过该方法改变接收者的成员变量值,即使你使用了非指针类型实例调用该函数,也可以改变对应的成员变量值。
package main
import "fmt"
type User struct {
Name string
Email string
}
func (u *User) ChangName() { //指针类型接收者
u.Name= "Tom"
}
func main() {
u := &User {"Peter", "go@go.com"} //创建指针类型结构体实例
fmt.Println("Name:",u.Name,"Email:",u.Email)
u.ChangName()
fmt.Println("Name:",u.Name,"Email:",u.Email)
}
或者
package main
import "fmt"
type User struct {
Name string
Email string
}
func (u *User) ChangName() { //指针类型接收者
u.Name= "Tom"
}
func main() {
u := User {"Peter","go@go.com"} //创建非指针类型结构体实例
fmt.Println("Name:",u.Name,"Email:",u.Email)
u.ChangName()
fmt.Println("Name:",u.Name,"Email:",u.Email)
}
执行结果:
Name: Peter Email: go@go.com
Name: Tom Email: go@go.com
值类型接收者
当接收者不是一个指针时,该方法的操作对应接收者的副本,否则即使你使用了指针调用函数,也无法改变成员变量值。
package main
import "fmt"
type User struct {
Name string
Email string
}
func (u User) ChangName() { //值类型接收者
u.Name= "Tom"
}
func main() {
u := &User {"Peter", "go@go.com"} //创建指针类型结构体实例
fmt.Println("Name:",u.Name,"Email:",u.Email)
u.ChangName()
fmt.Println("Name:",u.Name,"Email:",u.Email)
}
执行结果:
Name: Peter Email:go@go.com
Nmae: Peter Email:go@go.com
结构体内嵌
Go语言的结构体内嵌是一种组合特性,使用结构体内嵌可构建一种面向对象编程思想中的继承关系,结构体实例化后,可直接访问内嵌结构体的所有成员变量和方法。
type 结构体名1 struct {
成员变量1 类型1
成员变量2 类型2
}
type 结构体名2 struct {
结构体名1
成员变量3 类型3
}
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
type BookBorrow struct
{
Book
borrowTime string
}
type BookNotBorrow struct
{
Book
readTime string
}
func main() {
bookBorrow := &BookBorrow{}
bookNotBorrow := &BookNotBorrrow{}
fmt.Println(bookBorrow)
fmt.Println(bookNotBorrow)
}
初始化结构体内嵌
结构体内嵌的初始化和结构体初始化类似,可以使用键值对或“.”的方式来进行初始化
type 结构体名1 struct {
成员变量1 类型1
成员变量2 类型2
}
type 结构体名2 struct {
结构体名1
成员变量3 类型3
}
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
type BookBorrow struct
{
Book
borrowTime string
}
type BookNotBorrow struct
{
Book
readTime string
}
func main() {
bookBorrow := &BookBorrow{
Book:Book{"Go语言",
"Tom",
20,
152358,
},
borrowTime:"30",
}
fmt.Println(boookBorrow)
bookNotBorrow := &BookNotBorrrow{
}
bookNotBorrow.title="Python语言"
bookNotBorrow.author="Peter"
bookNotBorrow.num=10
bookNotBorrow.id=152359
bookNotBorrow.readTime="50"
fmt.Println(bookNotBorrow)
}
执行结果如下:
&{{Go语言 Tom 20 152358} 30}
&{{Python语言 Peter 10 152359} 50}
内嵌匿名结构体
在定义匿名结构体时,无须type关键字,但是在初始化被嵌入的匿名结构体时,需要再次声明结构体才能赋予数据
package main
import "fmt"
type BookBorrow struct {
Book struct { //内嵌匿名结构体
title string
author string
num int
id num
}
borrowTime string
}
func main() {
bookBorrow := &BookBorrow{
Book:struct { //声明类型
title string
author string
num int
id num
}{ "Go语言",
"Tom",
20,
152358,
},
borrowTime:"30",
}
fmt.Println(bookborrow)
}
匿名结构体
匿名结构体定义与初始化
title: Go语言
结构体实例 := struct{
//匿名结构体定义
成员变量1 类型1
成员变量2 类型2
成员变量3 类型3
...
}{
//成员变量初始化(可选)
成员变量1:值1,
成员变量2:值2,
成员变量3:值3,
...
}
匿名结构体的应用
匿名结构体一般用于组织全局变量、构建数据模板和解析JSON等