• 结构体之二


    1.3.14 结构体的匿名字段

    结构体允许其成员字段在声明时没有字段名而只有类型,这种没有名字的字段就称为匿名字段。

     
    //Person 结构体Person类型
    type Person struct {
        string
        int
    }
    
    func main() {
        p1 := Person{
            "pprof.cn",
            18,
        }
        fmt.Printf("%#v\n", p1)        //main.Person{string:"pprof.cn", int:18}
        fmt.Println(p1.string, p1.int) //pprof.cn 18
    }

    匿名字段默认采用类型名作为字段名,结构体要求字段名称必须唯一,因此一个结构体中同种类型的匿名字段只能有一个。

    1.3.15 嵌套结构体

    一个结构体中可以嵌套包含另一个结构体或结构体指针。

     
    //Address 地址结构体
    type Address struct {
        Province string
        City     string
    }
    
    //User 用户结构体
    type User struct {
        Name    string
        Gender  string
        Address Address
    }
    
    func main() {
        user1 := User{
            Name:   "pprof",
            Gender: "",
            Address: Address{
                Province: "黑龙江",
                City:     "哈尔滨",
            },
        }
        fmt.Printf("user1=%#v\n", user1)//user1=main.User{Name:"pprof", Gender:"女", Address:main.Address{Province:"黑龙江", City:"哈尔滨"}}
    }

    1.3.16 嵌套匿名结构体

    //Address 地址结构体
    type Address struct {
        Province string
        City     string
    }
    
    //User 用户结构体
    type User struct {
        Name    string
        Gender  string
        Address //匿名结构体
    }
    
    func main() {
        var user2 User
        user2.Name = "pprof"
        user2.Gender = ""
        user2.Address.Province = "黑龙江"    //通过匿名结构体.字段名访问
        user2.City = "哈尔滨"                //直接访问匿名结构体的字段名
        fmt.Printf("user2=%#v\n", user2) //user2=main.User{Name:"pprof", Gender:"女", Address:main.Address{Province:"黑龙江", City:"哈尔滨"}}
    }

    当访问结构体成员时会先在结构体中查找该字段,找不到再去匿名结构体中查找。

     1.3.17 嵌套结构体的字段名冲突

    嵌套结构体内部可能存在相同的字段名。这个时候为了避免歧义需要指定具体的内嵌结构体的字段。

     
    //Address 地址结构体
    type Address struct {
        Province   string
        City       string
        CreateTime string
    }
    
    //Email 邮箱结构体
    type Email struct {
        Account    string
        CreateTime string
    }
    
    //User 用户结构体
    type User struct {
        Name   string
        Gender string
        Address
        Email
    }
    
    func main() {
        var user3 User
        user3.Name = "pprof"
        user3.Gender = ""
        // user3.CreateTime = "2019" //ambiguous selector user3.CreateTime
        user3.Address.CreateTime = "2000" //指定Address结构体中的CreateTime
        user3.Email.CreateTime = "2000"   //指定Email结构体中的CreateTime
    }

    1.3.18 结构体的继承

    Go语言中使用结构体也可以实现其他编程语言中面向对象的继承。

     
    //Animal 动物
    type Animal struct {
        name string
    }
    
    func (a *Animal) move() {
        fmt.Printf("%s会动!\n", a.name)
    }
    
    //Dog 狗
    type Dog struct {
        Feet    int8
        *Animal //通过嵌套匿名结构体实现继承
    }
    
    func (d *Dog) wang() {
        fmt.Printf("%s会汪汪汪~\n", d.name)
    }
    
    func main() {
        d1 := &Dog{
            Feet: 4,
            Animal: &Animal{ //注意嵌套的是结构体指针
                name: "乐乐",
            },
        }
        d1.wang() //乐乐会汪汪汪~
        d1.move() //乐乐会动!
    }

    1.3.19 结构体字段的可见性

    结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问)。

     1.3.20 结构体与JSON序列化 (需要在看看)
    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON键值对是用来保存JS对象的一种方式,键/值对组合中的键名写在前面并用双引号""包裹,使用冒号:分隔,然后紧接着值;多个键值之间使用英文,分隔。
    //Student 学生
    type Student struct {
        ID     int
        Gender string
        Name   string
    }
    
    //Class 班级
    type Class struct {
        Title    string
        Students []*Student
    }
    
    func main() {
        c := &Class{
            Title:    "101",
            Students: make([]*Student, 0, 200),
        }
        for i := 0; i < 10; i++ {
            stu := &Student{
                Name:   fmt.Sprintf("stu%02d", i),
                Gender: "",
                ID:     i,
            }
            c.Students = append(c.Students, stu)
        }
        //JSON序列化:结构体-->JSON格式的字符串
        data, err := json.Marshal(c)
        if err != nil {
            fmt.Println("json marshal failed")
            return
        }
        fmt.Printf("json:%s\n", data)
        //JSON反序列化:JSON格式的字符串-->结构体
        str := `{"Title":"101","Students":[{"ID":0,"Gender":"","Name":"stu00"},{"ID":1,"Gender":"","Name":"stu01"},{"ID":2,"Gender":"","Name":"stu02"},{"ID":3,"Gender":"","Name":"stu03"},{"ID":4,"Gender":"","Name":"stu04"},{"ID":5,"Gender":"","Name":"stu05"},{"ID":6,"Gender":"","Name":"stu06"},{"ID":7,"Gender":"","Name":"stu07"},{"ID":8,"Gender":"","Name":"stu08"},{"ID":9,"Gender":"","Name":"stu09"}]}`
        c1 := &Class{}
        err = json.Unmarshal([]byte(str), c1)
        if err != nil {
            fmt.Println("json unmarshal failed!")
            return
        }
        fmt.Printf("%#v\n", c1)
    }

    1.3.21 结构体标签(Tag)

    Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。

    Tag在结构体字段的后方定义,由一对反引号包裹起来,具体的格式如下:

        `key1:"value1" key2:"value2"`

    结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔。 注意事项: 为结构体编写Tag时,必须严格遵守键值对的规则。结构体标签的解析代码的容错能力很差,一旦格式写错,编译和运行时都不会提示任何错误,通过反射也无法正确取值。例如不要在key和value之间添加空格。

    例如我们为Student结构体的每个字段定义json序列化时使用的Tag:

     
    //Student 学生
    type Student struct {
        ID     int    `json:"id"` //通过指定tag实现json序列化该字段时的key
        Gender string //json序列化是默认使用字段名作为key
        name   string //私有不能被json包访问
    }
    
    func main() {
        s1 := Student{
            ID:     1,
            Gender: "",
            name:   "pprof",
        }
        data, err := json.Marshal(s1)
        if err != nil {
            fmt.Println("json marshal failed!")
            return
        }
        fmt.Printf("json str:%s\n", data) //json str:{"id":1,"Gender":"女"}
    }

    1.3.22 小练习

    猜一下下列代码运行的结果是什么

     
    package main
    
    import "fmt"
    
    type student struct {
        id   int
        name string
        age  int
    }
    
    func demo(ce []student) {
        //切片是引用传递,是可以改变值的
        ce[1].age = 999
        // ce = append(ce, student{3, "xiaowang", 56})
        // return ce
    }
    func main() {
        var ce []student  //定义一个切片类型的结构体
        ce = []student{
            student{1, "xiaoming", 22},
            student{2, "xiaozhang", 33},
        }
        fmt.Println(ce)
        demo(ce)
        fmt.Println(ce)
    }

    1.3.23 删除map类型的结构体

    package main
    
    import "fmt"
    
    type student struct {
        id   int
        name string
        age  int
    }
    
    func main() {
        ce := make(map[int]student)
        ce[1] = student{1, "xiaolizi", 22}
        ce[2] = student{2, "wang", 23}
        fmt.Println(ce)
        delete(ce, 2)
        fmt.Println(ce)
    }

    1.3.24 实现map有序输出(面试经常问到)

    package main
    
    import (
        "fmt"
        "sort"
    )
    
    func main() {
        map1 := make(map[int]string, 5)
        map1[1] = "www.topgoer.com"
        map1[2] = "rpc.topgoer.com"
        map1[5] = "ceshi"
        map1[3] = "xiaohong"
        map1[4] = "xiaohuang"
        sli := []int{}
        for k, _ := range map1 {
            sli = append(sli, k)
        }
        sort.Ints(sli)
        for i := 0; i < len(map1); i++ {
            fmt.Println(map1[sli[i]])
        }
    }

    1.3.25 小案例

    采用切片类型的结构体接受查询数据库信息返回的参数

  • 相关阅读:
    demo_14 更多卡片视图实现
    demo_13 基础卡片视图实现
    demo_10_06 云数据库聚合_lookup_02
    demo_10_06 云数据库聚合_lookup_01
    demo_12 子组件选项卡切换及事件传递
    demo_11 封装数据请求
    demo_10_05 云数据库聚合_limit
    demo_10_04 云数据库聚合_group_02
    sed 过滤和替换文本函数
    curl 参数
  • 原文地址:https://www.cnblogs.com/ltyc/p/16353862.html
Copyright © 2020-2023  润新知