美文网首页
第10章-结构体

第10章-结构体

作者: Venture_Mark | 来源:发表于2018-10-15 16:30 被阅读0次

    一、结构体

    1.1 什么是结构体

    Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

    1.2 结构体的定义和初始化

    type struct_variable_type struct {
       member definition;
       member definition;
       ...
       member definition;
    }
    
    

    一旦定义了结构体类型,它就能用于变量的声明

    variable_name := structure_variable_type {value1, value2...valuen}
    
    

    初始化结构体

    1.按照顺序提供初始化值
    P := person{"Tom", 25}
    2.通过field:value的方式初始化,这样可以任意顺序
    P := person{age:24, name:"Tom"}
    3.new方式,未设置初始值的,会赋予类型的默认初始值
    p := new(person)
    p.age=24
    
    

    1.3 结构体的访问

    访问结构体成员(访问结构的各个字段)

    通过点.操作符用于访问结构的各个字段。

    package main
    
    import "fmt"
    
    type Books struct {
       title string
       author string
       subject string
       book_id int
    }
    
    func main() {
       var Book1 Books        /* 声明 Book1 为 Books 类型 */
       var Book2 Books        /* 声明 Book2 为 Books 类型 */
    
       /* book 1 描述 */
       Book1.title = "Go 语言"
       Book1.author = "www.runoob.com"
       Book1.subject = "Go 语言教程"
       Book1.book_id = 6495407
    
       /* book 2 描述 */
       Book2.title = "Python 教程"
       Book2.author = "www.runoob.com"
       Book2.subject = "Python 语言教程"
       Book2.book_id = 6495700
    
       /* 打印 Book1 信息 */
       fmt.Printf( "Book 1 title : %s\n", Book1.title)
       fmt.Printf( "Book 1 author : %s\n", Book1.author)
       fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
       fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)
    
       /* 打印 Book2 信息 */
       fmt.Printf( "Book 2 title : %s\n", Book2.title)
       fmt.Printf( "Book 2 author : %s\n", Book2.author)
       fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
       fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
    }
    
    

    结果

    Book 1 title : Go 语言
    Book 1 author : www.runoob.com
    Book 1 subject : Go 语言教程
    Book 1 book_id : 6495407
    Book 2 title : Python 教程
    Book 2 author : www.runoob.com
    Book 2 subject : Python 语言教程
    Book 2 book_id : 6495700
    
    

    1.4 结构体指针

    指针指向一个结构体 也可以创建指向结构的指针。

    结构体指针

    var struct_pointer *Books
    
    

    以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前

    struct_pointer = &Book1;
    
    

    使用结构体指针访问结构体成员,使用 “.” 操作符

    struct_pointer.title;
    
    
    package main
    
    import "fmt"
    
    type Books struct {
       title string
       author string
       subject string
       book_id int
    }
    
    func main() {
       var Book1 Books        /* Declare Book1 of type Book */
       var Book2 Books        /* Declare Book2 of type Book */
    
       /* book 1 描述 */
       Book1.title = "Go 语言"
       Book1.author = "www.runoob.com"
       Book1.subject = "Go 语言教程"
       Book1.book_id = 6495407
    
       /* book 2 描述 */
       Book2.title = "Python 教程"
       Book2.author = "www.runoob.com"
       Book2.subject = "Python 语言教程"
       Book2.book_id = 6495700
    
       /* 打印 Book1 信息 */
       printBook(&Book1)
    
       /* 打印 Book2 信息 */
       printBook(&Book2)
    }
    func printBook( book *Books ) {
       fmt.Printf( "Book title : %s\n", book.title);
       fmt.Printf( "Book author : %s\n", book.author);
       fmt.Printf( "Book subject : %s\n", book.subject);
       fmt.Printf( "Book book_id : %d\n", book.book_id);
    }
    
    

    结构体实例化也可以是这样的

    package main
    
    import "fmt"
    
    type Books struct {
    }
    
    func (s Books) String() string {
        return "data"
    }
    func main() {
        fmt.Printf("%v\n", Books{})
    }
    
    

    1.5 结构体的匿名字段

    结构体的匿名字段

    可以用字段来创建结构,这些字段只包含一个没有字段名的类型。这些字段被称为匿名字段。

    在类型中,使用不写字段名的方式,使用另一个类型

    type Human struct {
        name string
        age int
        weight int
    }
    type Student struct {
        Human // 匿名字段,那么默认Student就包含了Human的所有字段
        speciality string
    }
    func main() {
        // 我们初始化一个学生
        mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
        // 我们访问相应的字段
        fmt.Println("His name is ", mark.name)
        fmt.Println("His age is ", mark.age)
        fmt.Println("His weight is ", mark.weight)
        fmt.Println("His speciality is ", mark.speciality)
        // 修改对应的备注信息
        mark.speciality = "AI"
        fmt.Println("Mark changed his speciality")
        fmt.Println("His speciality is ", mark.speciality)
        // 修改他的年龄信息
        fmt.Println("Mark become old")
        mark.age = 46
        fmt.Println("His age is", mark.age)
        // 修改他的体重信息
        fmt.Println("Mark is not an athlet anymore")
        mark.weight += 60
        fmt.Println("His weight is", mark.weight)
    }
    
    

    可以使用”.”的方式进行调用匿名字段中的属性值

    实际就是字段的继承

    其中可以将匿名字段理解为字段名和字段类型都是同一个

    基于上面的理解,所以可以mark.Human = Human{"Marcus", 55, 220}mark.Human.age -= 1

    若存在匿名字段中的字段与非匿名字段名字相同,则最外层的优先访问,就近原则

    通过匿名访问和修改字段相当的有用,但是不仅仅是struct字段哦,所有的内置类型和自定义类型都是可以作为匿名字段的。

    1.6 结构体嵌套

    嵌套的结构体 一个结构体可能包含一个字段,而这个字段反过来就是一个结构体。这些结构被称为嵌套结构。

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    type Address struct {
        city, state string
    }
    type Person struct {
        name string
        age int
        address Address
    }
    
    func main() {
        var p Person
        p.name = "Naveen"
        p.age = 50
        p.address = Address {
            city: "Chicago",
            state: "Illinois",
        }
        fmt.Println("Name:", p.name)
        fmt.Println("Age:",p.age)
        fmt.Println("City:",p.address.city)
        fmt.Println("State:",p.address.state)
    }
    
    

    1.7 提升字段

    在结构体中属于匿名结构体的字段称为提升字段,因为它们可以被访问,就好像它们属于拥有匿名结构字段的结构一样。理解这个定义是相当复杂的。

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    type Address struct {
        city, state string
    }
    type Person struct {
        name string
        age  int
        Address
    }
    
    func main() {
        var p Person
        p.name = "Naveen"
        p.age = 50
        p.Address = Address{
            city:  "Chicago",
            state: "Illinois",
        }
        fmt.Println("Name:", p.name)
        fmt.Println("Age:", p.age)
        fmt.Println("City:", p.city) //city is promoted field
        fmt.Println("State:", p.state) //state is promoted field
    }
    
    

    运行结果

    Name: Naveen
    Age: 50
    City: Chicago
    State: Illinois
    
    

    1.8 导出结构体和字段

    如果结构体类型以大写字母开头,那么它是一个导出类型,可以从其他包访问它。类似地,如果结构体的字段以大写开头,则可以从其他包访问它们。

    示例代码:

    1.在computer目录下,创建文件spec.go

    package computer
    
    type Spec struct { //exported struct
        Maker string //exported field
        model string //unexported field
        Price int //exported field
    }
    
    

    2.创建main.go 文件

    package main
    
    import "structs/computer"
    import "fmt"
    
    func main() {
        var spec computer.Spec
        spec.Maker = "apple"
        spec.Price = 50000
        fmt.Println("Spec:", spec)
    }
    
    

    目录结构如下:

    src
      structs
          computer
              spec.go
          main.go
    
    

    1.9 结构体比较

    结构体是值类型,如果每个字段具有可比性,则是可比较的。如果它们对应的字段相等,则认为两个结构体变量是相等的。

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    type name struct {
        firstName string
        lastName string
    }
    
    func main() {
        name1 := name{"Steve", "Jobs"}
        name2 := name{"Steve", "Jobs"}
        if name1 == name2 {
            fmt.Println("name1 and name2 are equal")
        } else {
            fmt.Println("name1 and name2 are not equal")
        }
    
        name3 := name{firstName:"Steve", lastName:"Jobs"}
        name4 := name{}
        name4.firstName = "Steve"
        if name3 == name4 {
            fmt.Println("name3 and name4 are equal")
        } else {
            fmt.Println("name3 and name4 are not equal")
        }
    }
    
    

    运行结果

    name1 and name2 are equal
    name3 and name4 are not equal
    
    

    如果结构变量包含的字段是不可比较的,那么结构变量是不可比较的

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    type image struct {
        data map[int]int
    }
    
    func main() {
        image1 := image{data: map[int]int{
            0: 155,
        }}
        image2 := image{data: map[int]int{
            0: 155,
        }}
        if image1 == image2 {
            fmt.Println("image1 and image2 are equal")
        }
    }
    
    

    2.0 结构体作为函数的参数

    结构体作为函数参数使用

    ackage main
    
    import "fmt"
    
    type Books struct {
       title string
       author string
       subject string
       book_id int
    }
    
    func main() {
       var Book1 Books        /* 声明 Book1 为 Books 类型 */
       var Book2 Books        /* 声明 Book2 为 Books 类型 */
    
       /* book 1 描述 */
       Book1.title = "Go 语言"
       Book1.author = "www.runoob.com"
       Book1.subject = "Go 语言教程"
       Book1.book_id = 6495407
    
       /* book 2 描述 */
       Book2.title = "Python 教程"
       Book2.author = "www.runoob.com"
       Book2.subject = "Python 语言教程"
       Book2.book_id = 6495700
    
       /* 打印 Book1 信息 */
       printBook(Book1)
    
       /* 打印 Book2 信息 */
       printBook(Book2)
    }
    
    func printBook( book Books ) {
       fmt.Printf( "Book title : %s\n", book.title);
       fmt.Printf( "Book author : %s\n", book.author);
       fmt.Printf( "Book subject : %s\n", book.subject);
       fmt.Printf( "Book book_id : %d\n", book.book_id);
    }
    
    

    相关文章

      网友评论

          本文标题:第10章-结构体

          本文链接:https://www.haomeiwen.com/subject/lonfzftx.html