GO语言数据结构之结构体

结构体的定义

结构体是用户定义的类型,表示若干个字段(Field)的集合。有时应该把数据整合在一起,而不是让这些数据没有联系。这种情况下可以使用结构体。

结构体的声明

type Employee struct {
    FirstName string
    LastName  string
    Age       int
}
复制代码

配合结构体的typestruct关键字。Go语言的type关键字可以将各种基本类型定义为自定义类型,结构体的名称在同一个包里不能重复。如果需要结构体在包外也能够被访问,结构体的首字母要大写。结构体的字段名必须唯一,如果字段是公开的,字段名的首字母同样需要大写。

结构体的实例化和初始化

实例化为我们创建的结构体在内存中分配具体的内存进行存储,初始化为实例化好的结构体内的字段赋予初始值。

实例化

实例化将为结构体分配具体的内存用于存储字段,结构体必须在实例化后才能够使用。实例化会根据结构体的定义为结构体在内存中创建一份样式一致的内存区域用于存储结构体,每个结构体实例之间的内存区域是相互独立的。

像声明变量一样直接实例化结构体,然后对结构体字段进行赋值

// 声明实例化
var e1 Employee
e1.FirstName = "王"
e1.LastName = "小五"
e1.Age = 29
复制代码

new函数为结构体申请内存区域

e2 := new(Employee) //new函数实例化
e2.FirstName = "张"
e2.LastName = "三"
e2.Age = 28
复制代码

还可以通过&对结构体进行取址

e3 := &Employee{} //取址实例化
e3.FirstName = "张"
e3.LastName = "小六"
e3.Age = 27
复制代码

初始化

在实例化的过程中,就可以对结构体的字段进行初始化,使用类似JSON的键值对可以对结构体的数据进行赋值,字段的初始化是可选的。

package main

import (
    "fmt"
)

type Employee struct {
    FirstName, LastName string
    Age         int
}

func main() {

   
    emp1 := Employee{
        FirstName: "张",
        Age:       25, 
        LastName:  "小花",
    }


    emp2 := Employee{"李", "二牛", 29}

    fmt.Println("Employee 1", emp1)
    fmt.Println("Employee 2", emp2)
}
复制代码

输出如下:

Employee 1 {张 小花 25}
Employee 2 {李 二牛 29}
复制代码

当结构体所有字段都需要初始化时,并且字段的填充顺序与它们在结构体内定义的顺序一致时,可以将键值对的键省略。

结构体的字段有可能也是一个结构体。这样的结构体称为嵌套结构体。

package main

import (
    "fmt"
)

type Address struct {
    city, county string
}
type Person struct {
    name string
    age int
    address Address
}

func main() {
    var p Person
    p.name = "张翠花"
    p.age = 50
    p.address = Address {
        city: "广安",
        county: "花桥",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:",p.age)
    fmt.Println("City:",p.address.city)
    fmt.Println("County:",p.address.county)
}
复制代码

如果是结构体中有匿名的结构体类型字段,则该匿名结构体里的字段就称为提升字段。这是因为提升字段就像是属于外部结构体一样,可以用外部结构体直接访问。

package main

import (
    "fmt"
)

type Address struct {
    city, county string
}
type Person struct {
    name string
    age  int
    Address
}

func main() {
    var p Person
    p.name = "张青山"
    p.age = 35
    p.Address = Address{
        city:  "广安",
        county: "岳池",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:", p.age)
    fmt.Println("City:", p.city) //提升字段
    fmt.Println("County:", p.county) //提升字段
}
复制代码

p.citycounty,访问提升字段 citycounty 就像它们是在结构体 p 中声明的一样。该程序会输出:

Name: 张青山
Age: 35
City: 广安
County: 岳池
复制代码

方法

方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。

func (t Type) methodName(parameter list) {
}
复制代码

上面的代码片段创建了一个接收器类型为 Type 的方法 methodName。与普通函数相比,方法的定义中多了一个接收器的设定,每一个方法只能有一个接收器,接收器的概念就类似于面向对象的this或者self,可以直接在方法中使用接收器的相关属性。

接收器有两种类型,分别是指针类型和非指针类型的接收器。如果需对原成员属性进行修改时,应该使用指针类型接收器;

package main

import "fmt"


type Person struct {
	Name string	// 姓名
	Birth string	// 生日
	ID int64	// 身份证号
}

// 指针类型,修改个人信息
func (person *Person) changeName(name string)  {
	person.Name = name
}

// 非指针类型,打印个人信息
func (person Person) printMessage()  {
	fmt.Printf("My name is %v, and my birthday is %v, and my id is %v\n",
		person.Name, person.Birth, person.ID)

	// 尝试修改个人信息,但是对原接收器并没有影响
	person.ID = 3

}

func main()  {
		p1 := Person{
			Name:"王老五",
			Birth: "1992-12-22",
			ID:1,
		}

		p1.printMessage()
		p1.changeName("王老二")
		p1.printMessage()

}
复制代码

输出如下:

My name is 王小二, and my birthday is 1990-12-23, and my id is 1
My name is 王老二, and my birthday is 1990-12-23, and my id is 1
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享