一、结构体

实例化结构体

第一种实例化结构体:var 变量 结构体

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func main() {
    var p1 Person  // 实例化 Person 结构体
    p1.name = "张三"
    p1.sex = "男"
    p1.age = 20
    fmt.Printf("值:%v 类型:%T\n", p1, p1)
    fmt.Printf("值:%#v 类型:%T", p1, p1)
}

输出:

值:{张三 20 男} 类型:main.Person
值:main.Person{name:"张三", age:20, sex:"男"} 类型:main.Person

结构体首字母可以大写也可以小写,大写表示这个结构体是公有的,在其他包里面可以使用,小写表示这个结构体是私有的,只有在这个包里面才能使用。

第二种实例化结构体:new 关键词

在 Golang 中支持对结构体指针直接使用.来访问结构体的成员。p2.name = "张三" 其实在底层是 (*p2).name = "张三"

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func main() {
    var p2 = new(Person)
    p2.name = "李四"
    p2.sex = "男"
    p2.age = 20
    fmt.Printf("值:%v 类型:%T\n", p2, p2)
    (*p2).name = "王五"
    fmt.Printf("值:%v 类型:%T\n", p2, p2)
}

输出:

值:&{李四 20 男} 类型:*main.Person
值:&{王五 20 男} 类型:*main.Person

第三种实例化结构体:取结构体地址

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func main() {
    var p3 = &Person{}
    p3.name = "赵四"
    p3.sex = "男"
    p3.age = 20
    fmt.Printf("值:%v 类型:%T\n", p3, p3)
}

输出:

值:&{赵四 20 男} 类型:*main.Person

第四种实例化结构体:键值对

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func main() {
    var p4 = Person{
        name: "哈哈",  // 必须加,
        sex: "男",
        age: 20,
    }
    fmt.Printf("值:%v 类型:%T\n", p4, p4)
}

输出:

值:{哈哈 20 男} 类型:main.Person

第五种实例化结构体:键值对

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func main() {
    var p5 = &Person{
        name: "王二狗",
        sex: "男",
        age: 20,
    }
    fmt.Printf("值:%v 类型:%T\n", p5, p5)
}

输出:

值:&{王二狗 20 男} 类型:*main.Person

第六种实例化结构体:省略 key,但是顺序要一致

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func main() {
    var p6 = &Person{
        "狗蛋",
        20,
        "男",  
    }
    fmt.Printf("值:%v 类型:%T\n", p6, p6)
}

输出:

值:&{狗蛋 20 男} 类型:*main.Person

二、结构体方法

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func (p Person) PrintInfo() {
    fmt.Printf("姓名: %v 年龄: %v\n", p.name, p.age)
}

func main() {
    var p = Person{
        name: "张三",
        age: 20,
        sex: "男",  
    }
    p.PrintInfo()
}

输出:

姓名: 张三 年龄: 20

结构体是值类型。

Golang 中结构体实例是独立的,不会相互影响。

package main

import (
    "fmt"
)

type Person struct {
    name string
    age int
    sex string
}

func (p Person) PrintInfo() {
    fmt.Printf("姓名: %v 年龄: %v\n", p.name, p.age)
}

func (p *Person) SetInfo(name string, age int) {
    p.name = name
    p.age = age
}

func main() {
    var p1 = Person{
        name: "张三",
        age: 20,
        sex: "男",  
    }
    p1.PrintInfo()

    var p2 = Person{
        name: "王五",
        age: 22,
        sex: "男",  
    }

    p1.SetInfo("李四", 34)
    p1.PrintInfo()
    p2.PrintInfo()
}

输出:

姓名: 张三 年龄: 20
姓名: 李四 年龄: 34
姓名: 王五 年龄: 22

三、结构体嵌套和继承

结构体的匿名字段

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

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

package main

import (
    "fmt"
)

type Person struct {
    string
    int
}

func main() {
    p := Person{
        "张三",
        20,
    }
    fmt.Println(p)
}

输出:

{张三 20}

结构体带 map

package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age int
    Hobby []string
    map1 map[string]string
}

func main() {
    var p Person
    p.Name = "张三"
    p.Age = 20
    p.Hobby = make([]string, 3, 6)
    p.Hobby[0] = "写代码"
    p.Hobby[1] = "打篮球"
    p.Hobby[2] = "睡觉"

    p.map1 = make(map[string]string)
    p.map1["address"] = "北京"
    p.map1["phone"] = "1234567890"
    fmt.Printf("%#v\n", p)
    fmt.Printf("%v", p.Hobby)
}

输出:

main.Person{Name:"张三", Age:20, Hobby:[]string{"写代码", "打篮球", "睡觉"}, map1:map[string]string{"address":"北京", "phone":"1234567890"}}
[写代码 打篮球 睡觉]

结构体嵌套

package main

import (
    "fmt"
)

type User struct {
    Username string
    Password string
    Address Address
}

type Address struct {
    Name string
    Phone string
    City string
}

func main() {
    var u User
    u.Username = "张三"
    u.Password = "123456"
    u.Address.Name = "李四"
    u.Address.Phone = "1234567890"
    u.Address.City = "北京"
    fmt.Printf("%v\n", u)
}

输出:

{张三 123456 {李四 1234567890 北京}}

嵌套匿名结构体

package main

import (
    "fmt"
)

type User struct {
    Username string
    Password string
    Address
}

type Address struct {
    Name string
    Phone string
    City string
}

func main() {
    var u User
    u.Username = "张三"
    u.Password = "123456"
    u.Address.Name = "李四"
    u.Address.Phone = "1234567890"
    u.Address.City = "北京"
    fmt.Printf("%#v\n", u)
    fmt.Printf("%v\n", u)
}

输出:

{张三 123456 {李四 1234567890 北京}}

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

package main

import (
    "fmt"
)

type User struct {
    Username string
    Password string
    Address
}

type Address struct {
    Name string
    Phone string
    City string
}

func main() {
    var u User
    u.Username = "张三"
    u.Password = "123456"
    u.Address.Name = "李四"
    u.Address.Phone = "1234567890"
    u.City = "北京"
    fmt.Printf("%v\n", u)
    fmt.Printf("%v\n", u.City)
}

输出:

{张三 123456 {李四 1234567890 北京}}
北京

四、结构体继承

package main

import (
    "fmt"
)

// 父结构体
type Animal struct {
    Name string
}

func (a Animal) run() {
    fmt.Printf("%v 在运动\n", a.Name)
}

// 子结构体
type Dog struct {
    Age int
    Animal  // 结构体继承
}

func (d Dog) wang() {
    fmt.Printf("%v 在汪汪\n", d.Name)
}

func main() {
    var d = Dog{
        Age: 20,
        Animal: Animal{
            Name: "小黑",
        },
    }
    d.run()
    d.wang()
}

输出:

小黑 在运动
小黑 在汪汪

五、参考教程

Golang 教程 P31-P33