Skip to content

Go 语言笔记:结构体

结构体

结构体是一种将一个或者多个任意类型的值聚合的实体,每个值称为结构体的成员,其实结构体就是 Go 语言中的类。

结构体的声明

结构体可以使用以下格式进行声明

go
type struct_name struct {
  attribute_name attribute_type
  ...
}

例如我们定一个数据源实体 DataSource

go
type DataSource struct {
  url string
  user_name string
  password string
  driver_class_name string
}

成员的类型如果一致,可以定义在同一行,以逗号隔开

go
type DataSource struct {
  url, user_name, password, driver_class_name string
}

声明结构体也可以不使用 type 关键字,例如我们使用 var 关键字声明一个匿名的结构体

go
var DataSource struct {
  url string
  username string
  password string
}

结构体的创建

我们可以使用结构体成员名称来创建结构体,例如我们创建一个名为 Movie 的结构体,包含名称和上映年份成员。

go
type Movie struct {
  name string
  year int
}

使用成员名来初始化结构体

go
mov := Movie {
  name: "肖申克的救赎",
  year: 1994
}

不使用成员初始化结构体

go
mov := Movie {"肖申克的救赎", 1994}

初始化匿名结构体

go
mov := struct {
  name string,
  year int
} {
  name: "肖申克的救赎",
  year: 1994
}

结构体中的成员变量如果没有显示的赋值,那么它的值是初始化的零值,string 类型的零值为空字符串 ""int 类型的零值为 0。

结构体的使用

我们可以使用操作符 . 来给结构体的成员赋值,或者对其访问。

go
type Movie struct {
  name string
  year int
}

var mov = Movie {}
mov.name = "肖申克的救赎"
mov.year = 1994

fmt.Println(mov.name) // 肖申克的救赎
fmt.Println(mov.year) // 1994

除了以上使用创建出来的实体来访问其成员以外,我们也可以使用指针来访问

go
mov := &Movie {"肖申克的救赎", 1994}
fmt.Println((*mov).name) // 肖申克的救赎
fmt.Println(mov.name) // 肖申克的救赎

对于字段也匿名的结构体如何访问呢,且看下面的例子

go
type Movie struct {
  string
  int
}

mov := Movie{"肖申克的救赎", 1994}
fmt.Println(mov.string) // 肖申克的救赎

匿名字段只支持该类型在结构体中只有一个的情况才可以使用以上方式进行访问。

嵌套结构体

结构体的成员也可以是一个结构体,这样的结构体就是嵌套结构体

go
type Date struct {
  year, month, day int
}

type Movie struct {
  name string
  date Date
}

mov := Movie {
  name: "肖申克的救赎",
  date: Date {1994, 12, 12}
}

fmt.Println(mov.date.year) // 1994

结构体字段提升

结构体中如果有匿名的结构体类型,那么匿名的结构体中的字段则成为 提升字段, 提升字段的好处就是,可以直接使用外部结构体来访问,而不用像上面的必须通过中间的名称 mov.date.year 来访问。

go
type Date struct {
  year, month, day int
}

type Movie struct {
  name string
  Date
}

movies := Movie{name:"肖申克的救赎", Date: Date{1994, 12, 12}}

fmt.Println(movies.year) // 1994, 直接访问提升字段

结构体的方法

Go 语言结构体中无法直接定义方法,但是我们可以将方法绑定给某个结构体。

go
package main

import "fmt"

type Movie struct {
  name string
  year int
}

func (movie Movie) Display() {
  fmt.Println(movie.name)
  fmt.Println(movie.year)
}

func main() {
  mov := Movie{"肖申克的救赎", 1994}

  mov.Display()
}

// 打印结果:
肖申克的救赎
1994

结构体属性通过方法修改

结构体的属性需要通过方法来修改时,必须传递结构体的指针。

go
package main

import "fmt"

type Movie struct {
  name string
  year int
}

// 传递mov的副本,只能读取其属性的值,不能修改mov
func (movie Movie) display() {
  fmt.Println(movie.name)
  fmt.Println(movie.year)
}

// 传递指针,可以通过指针修改其属性的值
func (movie *Movie) Correct(year int) {
  movie.year = movie.year + year
}

func main() {
  mov := Movie{"肖申克的救赎", 1994}
  mov.Correct(1)
  fmt.Println(mov.year) // 1995
}

结构体方法的访问权限

Go 语言中,方法通过名称首字母的大小写来区分内部方法还是外部方法。

  • 当方法名称的首字母为大写时,该方法对于所有包都是 Public,其他包可以任意访问
  • 当方法名称的首字母为小写时,该方法是 Private,其他包是无法访问的

Released under the MIT License.