• Golang 结构体


    结构体说明

    结构体(struct) 是用户自定义的类型,它代表若干字段(基本数据类型/引用数据类型)的集合。有些时候将多个数据看做一个整体要比单独使用这些数据更有意义,这种情况下就适合结构体。

    比如将一个员工的name,department,salary三个属性打包在一起成为一个employee结构就很有意义的。

    结构体类型

    结构体是复合类型(composite types),当声明一个结构体变量的时候,内存空间就已经被分配,每个字段(field)为类型的0值。

    image-20211206163219437

    上面的内存示意图表明了,变量employee声明为Employee结构体类型的时候,会初始化该结构体中字段类型的0值,然后直接指向声明后的结构体,也可以说明:结构体类型。

    不同的结构体类型变量字段是独立的,互不影响,一个结构体变量字段的更改,不影响另外一个结构体类型变量。

    package main
    
    import "fmt"
    
    type Employee struct {
    	Name,Department string
    	Salary float32
    	Task []string
    }
    
    func main()  {
    	var employee1 = Employee{
    		Name: "易文杰",
    		Department: "系统开发部",
    		Salary: 5000,
    		Task: []string{
    			"支付",
    			"客户分配",
    		},
    	}
    
    	employee2 := employee1
    	employee2.Name = "张冲"
    
    	fmt.Println(employee1,employee2)
    }
    

    上面的代码,声明了一个employee1变量后,将employee1赋值给employee2变量,当我们修改employee2的字段Name后,发现emloyee1中的Name并没有被更改。程序的输出结果:

    {易文杰 系统开发部 5000 [支付 客户分配]} {张冲 系统开发部 5000 [支付 客户分配]}
    

    结构体的声明

    type Employee struct {
    	Name string
    	Department string
    	Salary float32
    }
    

    上面的代码声明了一个名为Employee的结构体类型,它拥有Name,Department,Salary三个字段。同一个类型的多个字段可以合并到一行(用逗号进行分隔),并将类型放到后面。上面的结构体中NameDepartment都是string的类型,因此可以将它们写到一起。

    type Employee struct {
    	Name,Department string
    	Salary float32
    }
    

    上面结构体Employee是一个具名结构体(named structure),因为它创建了一个具有名称的结构体类型:Employee。我们可以定义具名结构体类型的变量。

    我们也可以定义一个没有类型名称的结构体,这种结构体叫做匿名结构体(anonymous structures)

    var employee struct{
        Name,Department string
        Salary float32
    }
    

    当结构体中的字段是mapslice,指针的时候,默认的0值是nil(没有分配空间)的时候,需要分配空间后才能被使用

    package main
    
    import "fmt"
    
    type Employee struct {
    	Name,Department string
    	Salary float32
    	Mapper map[string]string
    	Slicer []string
    	Ptr *int
    }
    
    func main()  {
    	var employee Employee
    
    	employee.Name = "易文杰"
    	employee.Department = "系统开发部"
    
    	employee.Mapper = make(map[string]string)
    	employee.Mapper["smile"] = "易文杰"
    
    	employee.Slicer = make([]string,10)
    	employee.Slicer[0] = "切片"
    
    	age := 12
    	employee.Ptr = &age
    
    	fmt.Println(employee)
    }
    
    

    当未分配空间就直接使用,会导致代码异常

    panic: assignment to entry in nil map
    

    上面的程序会输出:

    {易文杰 系统开发部 0 map[smile:易文杰] [切片         ] 0xc00000a098}
    

    结构体的作用域

    结构体采用首字母大小写来区分访问权限,当首字母是大写,可以别外包引用。反之,不能。

    定义具名结构体变量

    下面的程序说明了如何定义一个具名结构体Employee的变量

    package main
    
    import "fmt"
    
    //定义结构体
    type Employee struct {
    	Name,Department string
    	Salary float32
    }
    
    func main()  {
    	//使用结构体一
    	employee1 := Employee{
    		Name: "易文杰",
    		Department: "系统研发部",
    		Salary: 5000,
    	}
    
    	//使用结构体二
    	employee2 := Employee{"张冲","系统研发部",15000}
    
    	fmt.Println(employee1,employee2)
    }
    

    在上面的程序中,我们定义了一个名叫Employee的结构体类型,我们可以通过指定字段的名称和对应的值来创建一个结构体变量。其中字段名和类型必须要和结构体中声明的保持一致。

    采用第一种定义结构体变量:不需要和声明结构体中的变量顺序保持一致,但最后一个数据需保留,

    采用第二种定义结构体变量:需要和声明结构体中的变量顺序保持一致,最后一个数据不需要保留,

    上面的程序输出如下:

    {易文杰 系统研发部 5000} {张冲 系统研发部 15000}
    

    定义匿名结构体变量

    package main
    
    import "fmt"
    
    func main()  {
    	var employee = struct {
    		Name,Department string
    		Salary float32
    	}{"张冲","系统开发部",28000}
    
    	fmt.Println(employee)
    }
    

    在上面的程序中,我们定义了一个employee匿名结构体变量。这种结构体称为匿名结构体,因为它只创建了一个新的结构体变量employee,而没有定义新的结构体类型。

    上面的程序输出为:

    {张冲 系统开发部 28000}
    

    访问结构体中的字段

    使用.操作符来访问结构体中的字段

    package main
    
    import "fmt"
    
    func main()  {
    	var employee = struct {
    		Name,Department string
    		Salary float32
    	}{"张冲","系统开发部",28000}
    
    	fmt.Printf("姓名%v\n部门%v\n工资%v\n",employee.Name,employee.Department,employee.Salary)
    }
    

    在上面的程序中,通过employee.Name来访问employee中的字段Name。程序的输出为:

    姓名张冲
    部门系统开发部
    工资28000
    

    结构体指针

    可以定义指向结构体的指针。

    package main
    
    import "fmt"
    
    type Employee struct {
    	Name,Department string
    	Salary float32
    }
    
    func main()  {
    	//方式一
    	var employee1 = &Employee{
    		Name: "张冲",
    		Department: "系统研发部",
    		Salary: 18000,
    	}
    
    	//方式二
    	var employee2 = new(Employee)
    	employee2.Name = "易文杰"
    
    	fmt.Println(employee1.Name)
    	fmt.Println((*employee1).Name)
    
    	fmt.Println(employee2.Name)
    	fmt.Println((*employee2).Name)
    }
    

    上面的程序中,employee1employee2是一个指向Employee结构体的指针。(*employee1).Name是访问employee1中的Name字段。程序的输出为:

    张冲
    张冲
    易文杰
    易文杰
    

    在Go中我们可以使用employee.Name替代显示解引用(*employee).Name来访问Name字段。

  • 相关阅读:
    CentOS6 配置阿里云 NTP 服务
    使用docker-compose运行nginx容器挂载时遇到的文件/目录问题
    Springboot配置文件参数使用docker-compose实现动态配置
    Dockerfile文件全面详解
    docker 生成mysql镜像启动时自动执行sql
    CentOS无法识别NTFS格式U盘完美解决方案
    网络模型与网络策略
    k8s更换网络插件:从flannel更换成calico
    数据采集实战(四)-- 线性代数习题答案下载
    leedcode 146. LRU 缓存机制(哈希+双向链表)
  • 原文地址:https://www.cnblogs.com/ywjcqq/p/15656563.html
Copyright © 2020-2023  润新知