[golang] 语法基础之结构体

Posted liujunhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[golang] 语法基础之结构体相关的知识,希望对你有一定的参考价值。

说明

Go语言是一种静态类型的编程语言。正因为如此,编译器就需要在进行编译时知道程序当中每个值的类型。当知道了这些类型信息,编译器就可以合理的使用值。这样的一种形式能够减少潜在的内存异常和bug,同时使编译器有机会对代码进行一定的性能优化,提高执行效率。

在go语言当中允许用户进行自定义类型。当用户新创建一个类型时,这个声明就给了编译器提供了一个框架,通过这个框架将必要的内存大小和表示信息告诉编译器。

Go语言里声明用户定义的类型有两种方法。最常用的方法是使用关键字struct,它可以让用户创建一个结构类型。而另外一种是之前说过的通过type自定义类型。

通过结构体,可以创建带有成员的复合类型。

使用

结构体成员是由一系列的成员变量构成,这些成员变量也被称为“字段”。字段有以下特性:

  • 字段拥有自己的类型和值。
  • 字段名必须唯一。
  • 字段的类型也可以是结构体,甚至是字段所在结构体的类型。

例如:

// user: 在程序中定义一个用户类型
type user struct {
    name string 
    age int 
    email string 
}

在上面的代码中,定义了一个结构体,并且在结构体当中设置了name、age和email字段。通过代码可以看到,每个字段都是一个已知类型,当然也可以是用户定义的其他类型。

上面定义了一个结构体,下面就可以使用这个结构体来进行声明变量。

var zhangsan user 

在上面的代码中创建了一个类型为user 且 值为zhangsan的一个变量。 当声明变量时,这个变量对应的值总是会被初始化。这个值要么用指定的值初始化,要么用零值(即变量类型的默认值)做初始化。对数值类型来说,零值是0;对字符串来说,零值是空字符串;对布尔类型,零值是false。对这个例子里的结构,结构里每个字段都会用零值初始化。

任何时候,创建一个变量并初始化为其零值,习惯是使用关键字var。这种用法是为了更明确地表示一个变量被设置为零值。

上面创建了一个变量zhangsan,如果想要对其初始化,可以采用下面的形式:

var zhangsan user 
zhangsan.name = "张三"
zhangsan.age = 30 
zhangsan.email = "zhangsan@qq.com"

如果变量被初始化为某个非零值,就配合结构字面量和短变量声明操作符来创建变量。

// 声明lisi这个变量并且设置为user类型同时进行初始化操作
lisi := user {
    name: "李四",
    email: "lisi@qq.com",
    age: 30 
}

上面的代码中,通过字面量和短变量操作符的方式声明了一个user类型的变量lisi并且进行了初始化。

结构体的初始化除了上面的两种形式以外,还可以采用下面的这种形式,按照结构体当中字段的顺序来进行赋值初始化。

zhangxiaoxiao := user{"张晓晓",30,"zhangxiaoxiao@qq.com"}

每个值也可以分别占一行,不过习惯上这种形式会写在一行里,结尾不需要逗号。这种形式下,值的顺序很重要,必须要和结构声明中字段的顺序一致。当声明结构类型时,字段的类型并不限制在内置类型,也可以使用其他用户定义的类型。

// admin 需要一个user类型作为管理者并且附加权限
type admin struct {
    person user
    level string
}

在上面的代码中,展示了一个名为admin的新结构类型。这个结构类型有一个名为person的user类型的字段,还声明了一个名为level的string字段。当创建具有person这种字段的结构类型的变量时,初始化用的结构字面量会有一些变化。

root := admin {
    person: user {
        name : "root",
        age : 30 ,
        email: "root@qq.com"
    },
    level: "super",
}

在上面的代码中,创建了一个admin类型的变量结构体root,在上面初始化的过程中,分别初始化了user结构体和level这个变量。

为结构体分配内存并初始化

上面其实我们已经说过go的结构体初始化,但是在go中对结构体进行初始化除了上述的方法以外,还可以使用new函数分配内存后再进行初始化。

具体写法如下:

ins := new(T)

其中:

  • T 为类型,可以是结构体、整型、字符串等。
  • ins:T 类型被实例化后保存到 ins 变量中,ins 的类型为 *T,属于指针。

需要知道的是,在通过new分配内存后,结构体在实例化后会形成指针类型的结构体。

下面的例子定义了一个玩家(Player)的结构,玩家拥有名字、生命值和魔法值,实例化玩家(Player)结构体后,可对成员进行赋值,代码如下:

type Player struct{
    Name string
    HealthPoint int
    MagicPoint int
}
tank := new(Player)
tank.Name = "Canon"
tank.HealthPoint = 300

经过 new 实例化的结构体实例在成员赋值上与基本实例化的写法一致。

通过取结构体地址实例化

在Go语言中,对结构体进行&取地址操作时,视为对该类型进行一次 new 的实例化操作,取地址格式如下:

ins := &T{}

其中:

  • T 表示结构体类型。
  • ins 为结构体的实例,类型为 *T,是指针类型。

下面使用结构体定义一个命令行指令(Command),指令中包含名称、变量关联和注释等,对 Command 进行指针地址的实例化,并完成赋值过程,代码如下:

type Command struct {
    Name    string    // 指令名称
    Var     *int      // 指令绑定的变量
    Comment string    // 指令的注释
}
var version int = 1
cmd := &Command{}
cmd.Name = "version"
cmd.Var = &version
cmd.Comment = "show version"

取地址实例化是最广泛的一种结构体实例化方式,可以使用函数封装上面的初始化过程,代码如下:

func newCommand(name string, varref *int, comment string) *Command {
    return &Command{
        Name:    name,
        Var:     varref,
        Comment: comment,
    }
}
cmd := newCommand(
    "version",
    &version,
    "show version",
)

以上是关于[golang] 语法基础之结构体的主要内容,如果未能解决你的问题,请参考以下文章

Golang基础之结构体

golang快速入门数据类型特别之处(下)

golang 碎片整理之 结构体

golang之结构体和方法

golang之结构体

Golang 学习之路