Go 语言数据结构:结构体


指针

Go提供了指针类型。指针保存的是一个值的内存地址。但是Go没有指针运算。 类型*T是指向T值的指针。它的零值为nil。

var p *int

*& 运算符生成指向其操作数的指针。 **运算符表示指针的基本值。

i := 42
p = &i

fmt.Println(*p) // read i through the pointer p
*p = 21         // set i through the pointer p

结构体(Structs)

  • Go语言中,结构体是一种用户自定义的数据类型,用于存储不同数据类型的集合 。
  • 使用点(.)访问结构字段。
  • 在结构体中,字段首字母的大小写决定了该字段的可见性。

定义结构体

一个结构体包含0到N个字段(Field),每个字段由字段名和类型构成;定义一个结构体的一般方式如下,

type T struct {
    field1 type1
    field2 type2
    ...
}

如果个字段类型相同也可以简写成 :

type T struct {X,Y int}

创建结构体

假设我们已经定义了这样一个结构体:

type Vertex struct {
    X int
    Y int
}

如何使用这个结构体呢?创建一个结构体变量常用的方法有:

  • 定义结构体类型变量
var v1 Vertex
v1.X = 1
v1.Y = 2
fmt.Println(v1) // 输出 {1 2}
  • 定义变量并赋值 (可以只指定部分字段的值,未指定的字段默认为该字段类型的零值)
v1 := Vertex{X:1,Y:2}
v2 := Vertex{3,4} // 也可以不显示字段名,按字段的顺序进行赋值
fmt.Println(v1,v2,v3) // 输出 {1 2} {3 4}

也可以不显示字段名,直接按字段的顺序进行赋值(如v2)。但这种方式可读性会差一些;

结构体指针

可以通过结构指针访问结构字段。(&返回一个指向结构值的指针)

v := Vertex{1, 2}
p := &v
p.X = 1e9
fmt.Println(v) //output {1000000000 2}

当我们通过结构指针p访问结构的字段X,可以这样写(*p).X。然而,这种表示法很麻烦,所以Go语言允许只写p.X,而不显式解引用。

Structs 等于 Class 吗?

Go语言中没有类的概念,而是提供了结构体,结构体中可以添加方法;这一点与类颇为相似;但是Go中的结构体没有继承的概念;以至于有人问:Is Go an object-oriented language?(Go是一种面向对象的语言吗) 我们看一下官方的回答: image.png

可以说是,也可以说不是。虽然 Go 有类型和方法,支持面向对象的编程风格,但却没有类型的层次结构。Go 中的“接口”概念提供了一种与众不同的方式,我们认为这种方式更易于使用,也更为通用。Go 也可以将结构体嵌套使用,这与子类化(Subclassing)类似,但并不完全相同。此外,Go 提供的特性比 C++ 或 Java 更为通用:子类可以由任何类型的数据来定义,甚至是内建类型(如简单的“未装箱的”整型)。这在结构体(类)中没有受到限制。 此外,由于缺乏类型层次结构,Go中的“对象”感觉比C++或Java等语言中的“对象”轻量得多。

因此在使用Go语言的结构体时需要用Go的思维方式去编写;比如下面的例子:

type Vertex struct {
    X int
    Y int
}
var v1 Vertex

fmt.Println(v1) // 输出 {0 0}

如果某类型的零值不可用,需要程序员来隐藏该类型,避免从其他包直接访问。并且提供一个New 函数让调用者按照要求初始化,例如:

type vertex struct {
    x int
    y int
}
func New(x,y int) vertex {
    return vertex{x:x,y:y}
}

func(v vertex) Mul() int {
    return v.x*v.y
}

调用者需要这样使用:

v := New(10,10)
m := v.Mul()
fmt.Println(m)

欢迎关注

如有疑问关注公众号给我留言
wx

关注公众号领取Go学习资料

wx

洋葱小店

©2017-2023 鲁ICP备17023316号-1 Powered by Hugo