Go语言入门16:结构体
Table of Contents
Go 语言入门基础学习笔记之 Go 语言的结构体
结构体
Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项、定义不同的数据类型。
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性:
- Title :标题
- Author : 作者
- Subject:学科
- ID:书籍 ID
Go 语言中的所谓对象实际上就是结构体。
结构体不是一个引用数据类型,因此结构体作为函数参数传递进函数时,会拷贝一个副本传递进去。这不同于切片 Slice 和集合 Map。
定义结构体
结构体定义需要使用 type
和 struct
语句。struct
语句定义一个新的数据类型,结构体中有一个或多个成员。type
语句设定了结构体的名称。结构体的格式如下:
type struct_variable_type struct {
member definition
member definition
...
member definition
}
一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:
variable_name := structure_variable_type {value1, value2...valuen}
// 或者
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
不是所有的成员变量都需要在声明时赋值,不赋值时,默认为该类型的空值
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
// 输出结果
{Go 语言 www.runoob.com Go 语言教程 6495407}
{Go 语言 www.runoob.com Go 语言教程 6495407}
{Go 语言 www.runoob.com 0}
Go 中的结构体不仅可以有成员变量,也可以有成员方法。成员方法在函数章节中已经讲解过了。
访问结构体成员
如果要访问结构体成员,需要使用点号 .
操作符,格式为:
结构体.成员名
结构体作为函数参数
你可以像其他数据类型一样将结构体类型作为参数传递给函数。
需要注意的是,结构体并不是一种引用数据类型,因此作为函数参数传递时会拷贝出一个副本传递,不会修改原来的结构体变量。如果需要在函数中修改原来的变量,则需要使用结构体指针传递。
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700
/* 打印 Book1 信息 */
printBook(Book1)
/* 打印 Book2 信息 */
printBook(Book2)
}
func printBook( book Books ) {
fmt.Printf( "Book title : %s\n", book.title)
fmt.Printf( "Book author : %s\n", book.author)
fmt.Printf( "Book subject : %s\n", book.subject)
fmt.Printf( "Book book_id : %d\n", book.book_id)
}
// 输出结果
Book title : Go 语言
Book author : www.runoob.com
Book subject : Go 语言教程
Book book_id : 6495407
Book title : Python 教程
Book author : www.runoob.com
Book subject : Python 语言教程
Book book_id : 6495700
结构体指针
你可以定义指向结构体的指针类似于其他指针变量。
var struct_pointer *Books
以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前。
struct_pointer = &Book1
使用结构体指针访问结构体成员,使用 .
操作符。
struct_pointer.title
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700
/* 打印 Book1 信息 */
printBook(&Book1)
/* 打印 Book2 信息 */
printBook(&Book2)
}
func printBook( book *Books ) {
fmt.Printf( "Book title : %s\n", book.title)
fmt.Printf( "Book author : %s\n", book.author)
fmt.Printf( "Book subject : %s\n", book.subject)
fmt.Printf( "Book book_id : %d\n", book.book_id)
}
// 输出结果
Book title : Go 语言
Book author : www.runoob.com
Book subject : Go 语言教程
Book book_id : 6495407
Book title : Python 教程
Book author : www.runoob.com
Book subject : Python 语言教程
Book book_id : 6495700
注意:在 Go 语言中,结构体指针的访问方式与普通指针的访问方式有所不同。
我们可以直接通过指针访问该结构体的字段,而不需要使用解引用符 *
。这是因为 Go 在处理结构体指针时做了一些简化。
- 指针接收者:在函数内部,接收到的指针
book
可以直接访问其指向的结构体的字段。这是 Go 的设计特性,旨在减少冗余。 - 自动解引用:在 Go 中,当你对一个指向结构体的指针使用点操作符(
.
)时,编译器会自动解引用这个指针。这意味着你可以像访问结构体本身一样访问其字段。
因此在上述例子中,不需要写作 (*book).title
,编译器会处理这个解引用。
函数与成员方法
Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。语法格式如下:
func (variable_name variable_data_type) function_name() [return_type]{
/* 函数体*/
}
与定义函数的区别在于,结构体成员方法在方法名前面还需要加上一个 ()
里面填入结构体的类型名和变量名,这里的变量名不建议使用 this self
等,比如:
func (u User) GetAge() int { // user结构体类型的变量u的一个成员方法GetAge()
return u.age
}
func (u *User) SetAge(a int) int {
u.age = a
}
需要注意的是,成员方法实际上等价于普通函数:
// 函数参数传递的是User的拷贝
func GetAge(u user) int {
return u.age
}
// 函数参数传递的是User的指针
func SetAge(u *User, a int) {
u.age = a
}
下面定义一个结构体类型和该类型的一个方法
package main
import (
"fmt"
)
/* 定义结构体 */
type Circle struct {
radius float64
}
func main() {
var c1 Circle
c1.radius = 10.00
fmt.Println("圆的面积 = ", c1.getArea())
}
//该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
//c.radius 即为 Circle 类型对象中的属性
return 3.14 * c.radius * c.radius
}
// 输出结果
圆的面积 = 314
Go 语言里不存在静态成员,所有成员变量和成员方法只能通过结构体的实例来访问。
Go 语言不存在狭义上的继承,但是可以把一个结构体作为另一个结构体的成员变量的类型。即可以把一个结构体类型当成一个基础的数据类型。
type Leader struct {
TeamSize int
human User // User是一个结构体类型
}
var l Leader // 声明结构体变量后,其成员变量均为空值
l.human = User(name: "Pi3", age: 18)
l.human = SetAge(l.human.GetAge() + 10) // 可以通过human调用User的方法
参考课程: