结构体 - Go 语言学习笔记

概述

结构体是一种聚合的自定义数据类型,是由零个或任意多个相同或不一样类型的变量聚合而成的数据集合,每一个变量称为结构体成员(也可称之为成员变量,字段,属性)。bash

定义结构体

使用 type 和 struct 语句定义结构体,type 语句设定告终构体的类型名称,struct 语句定义一个新的数据类型,结构体中有一个或多个成员。函数

格式以下:布局

/* 
type 类型名 struct {
    字段1  字段1类型
    字段2  字段2类型
    …
    字段3  字段3类型
}
*/
type struct_variable_type struct {
    member definition;
    member definition;
    ...
    member definition;
}

// 或者 同一类型的字段,能够定义在一行
type Color struct {
    R, G, B byte
}

复制代码

注意:ui

  1. 若是一个结构体的成员变量名称是首字母大些的,那么这个变量是可导出的(即在其它包能够访问到),反之不可导出。以下:
type A struct {
    Hour int    // 可导出
    minute int  // 不可导出
}
复制代码
  1. 结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存。

结构体实例化

  1. 经过 var 声明结构体完成实例化

结构体自己是一种类型,能够像整型、字符串等类型同样,以 var 的方式声明结构体便可完成实例化。spa

structure_variable_type 为结构体类型,variable_name 为结构体的实例。指针

// 给 variable_name 分配内存,并零值化内存,可是这个时候的 variable_name 的类型是 structure_variable_type
var variable_name structure_variable_type
复制代码
  1. 使用 new() 实例化

使用 new 函数给一个新的结构体变量分配内存,它返回指向已分配内存的指针:var variable_name *structure_variable_type = new(structure_variable_type)code

variable_name := new(structure_variable_type)
复制代码
  1. 使用字面量初始化
variable_name := structure_variable_type {value1, value2, valuen3}
或
variable_name := structure_variable_type {key1: value1, key2: value2, key3: value3}

variable_name := &structure_variable_type {value1, value2, valuen3}  // 等效于 new(structure_variable_type)
复制代码

使用结构体

1. 访问结构体成员

要访问结构体成员,须要使用点号 . 操做符,格式为:内存

// 结构体.成员名
type Point struct {
    X int
    Y int
}
var p Point
p.X = 10
p.Y = 20
复制代码

2. 比较结构体

若是结构体的全部成员变量均可以比较,那么这个结构体是能够比较的。两个结构体的比较可使用 == 或者 !=。ci

例如:字符串

type C struct {
    A int
    B string
}
c1 := C{A:1, B:"abc"}
c2 := C{A:1, B:"abc"}
c3 := C{A:2, B:"abc"}
fmt.Println(c1.A == c2.A && c1.B == c2.B)   // true
fmt.Println(c1 == c2)                       // true 与上等价
fmt.Println(c1.A == c3.A && c1.B == c3.B)   // false
fmt.Println(c1 == c3)                       // false 与上等价
复制代码

和其余可比较的类型同样,可比较的结构体类型均可以做为map的键类型。

例如:

type C struct {
    A int
    B string
}
mp := make(map[C]int)
key := C{A:1, B:"abc"}
mp[key] = 9
fmt.Println(mp[C{A:1, B:"abc"}])    // 9
复制代码

3. 结构体嵌套和匿名成员

Go语言容许咱们定义不带名称的结构体成员,只须要指定类型便可;这种结构体成员称做匿名成员。这个结构体成员的类型必须是一个命名类型或者指向命名类型的指针。正是由于有了这种结构体嵌套的功能,咱们才能直接访问到咱们须要的变量而不是指定一大串中间变量。

type Point struct {
    X int
    Y int
}
type Circle struct {
    Point
}
var c Circle
c.X = 10    // 等价于 c.Point.X = 10
c.Y = 10    // 等价于 c.Point.Y = 10

type Wheel struct {
    *Point
}
复制代码

结构体字面量初始化没有快捷方式,必须遵循形状类型的定义。

type Point struct {
    X int
    Y int
}
type Circle struct {
    Point
}
var c Circle
c = Circle{1,1}                 // 错误
c = Circle{Point{1,1}}          // 正确
c = Circle{Point: Point{1,1}}   // 正确
复制代码

由于“匿名成员”拥有隐式的名字,因此你不能在一个结构体里面定义两个相同类型的匿名成员,不然会引发冲突。因为匿名成员的名字是由它们的类型决定的,所以它们的可导出性也是由他们的的类型决定。在下面的例子中,point和circle这两个匿名成员是可导出的,即便这两个结构体是不可导出的(point和circle)。

type point struct {
    X int
    Y int
}
type circle struct {
    point
}
type Wheel struct {
    circle
}
var w Wheel
w.X = 8     // 等价于 w.circle.point.X = 8, w.X是可导出的,w.circle.point.X是不可导出的
复制代码

4. 结构体做为函数参数

能够像其余数据类型同样将结构体类型做为参数传递给函数。并以实例的方式访问结构体变量。 例如:

package main

import "fmt"

type Books struct {
    title string
    author string
    subject string
    book_id int
}

func changeBook(book Books) {
    book.title = "book1_change"
    fmt.Println(book)
}

func main() {
    var book1 Books;
    book1.title = "book1"
    book1.author = "zuozhe"
    book1.book_id = 1
    changeBook(book1)
    fmt.Println(book1)
}
复制代码

函数中结构体做为参数,若是不是用结构指针,函数内参数属性的改变不影响原来结构体数据。 结果为:

{book1_change zuozhe  1}
{book1 zuozhe  1}
复制代码

5. 结构体指针

能够定义指向结构体的指针相似于其余指针变量,格式以下:

var struct_pointer *Books
复制代码

以上定义的指针变量能够存储结构体变量的地址。查看结构体变量地址,能够将 & 符号放置于结构体变量前:

struct_pointer = &Book1
复制代码

使用结构体指针访问结构体成员,使用 "." 操做符:

struct_pointer.title
复制代码
相关文章
相关标签/搜索