Go语言入门16:结构体

Keywords: #技术 #Golang #Go入门笔记
Table of Contents

Go 语言入门基础学习笔记之 Go 语言的结构体

golang

结构体

Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项、定义不同的数据类型

结构体是由一系列具有相同类型不同类型的数据构成的数据集合

结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性:

  • Title :标题
  • Author : 作者
  • Subject:学科
  • ID:书籍 ID

Go 语言中的所谓对象实际上就是结构体。

结构体不是一个引用数据类型,因此结构体作为函数参数传递进函数时,会拷贝一个副本传递进去。这不同于切片 Slice集合 Map

定义结构体

结构体定义需要使用 typestruct 语句。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的方法

参考课程:

  1. 8小时转职Golang工程师
  2. Go语言教程 | 菜鸟教程
昵称
邮箱
网址
0/500
0 条评论