• [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",
    )
    
  • 相关阅读:
    不懂不可耻,可耻的是每当遇到不懂的东西不是想办法去学去了解而是极力掩饰。
    在咱学校的论坛上看到的一句话,觉得……我们都在等待某个人,等到累了,就随便牵起某人的手,默默地走进礼...
    在Linux下用Virtualbox虚拟机安装Windows XP
    大学里的挂科是对考前三天不用功的惩罚.这是教算法的赵PZ讲的,窃以为很有道理。可是接下来的十一天里我...
    壮哥!才发现你博客里这么多好东西,慢慢欣赏了,哈哈~~~~~~~~~~
    哥们现在用的什么?ghs不是又被封了吗
    提取字符串中的数字并分别保存
    十一天八考之路
    WPF使ListBox支持手势多选功能
    动手实现扩展属性为对象动态添加获取数据(续)
  • 原文地址:https://www.cnblogs.com/liujunhang/p/12535009.html
Copyright © 2020-2023  润新知