Skip to content

Struct

声明格式

type 类型名 struct {
    字段名 字段类型
    字段名 字段类型
    ...
}

结构体实例化

package main

import "fmt"

type Student struct {
    name string
    age  int
    city string
}

func main() {
    // 方式1
    var s1 Student
    s1 = Student{
        name: "mike",
        age:  18,
        city: "beijing",
    }

    // 方式2
    s2 := Student{
        name: "john",
        age:  18,
        city: "shanghai",
    }

    // 方式3
    var s3 Student
    s3.name = "jack"
    s3.age = 18
    s3.city = "guangzhou"

    fmt.Println(s1) // {mike 18 beijing}
    fmt.Println(s2) // {john 18 shanghai}
    fmt.Println(s3) // {jack 18 guangzhou}
}

匿名结构体

func main() {
    var s4 struct {
        name string
        age  int
        city string
    }
    s4.name = "rose"
    s4.age = 18
    s4.city = "shenzhen"

    fmt.Println(s4) // {rose 18 shenzhen}
}

类型定义和类型别名的区别

type myInt int
type newInt = int

func main() {
    var i myInt = 8
    var j int = 8
    var k newInt = 8
    fmt.Printf("%T %v\n", i, i) // main.myInt 8
    fmt.Printf("%T %v\n", j, j) // int 8
    fmt.Printf("%T %v\n", k, k) // int 8
}

结构体指针

func main() {
    // 方式1
    var s1 *Student
    s1 = new(Student)
    fmt.Printf("%p %T %#v\n", s1, s1, s1)

    // 方式2
    var s2 = new(Student)
    fmt.Printf("%p %T %#v\n", s2, s2, s2)

    // 方式3
    s3 := new(Student)
    fmt.Printf("%p %T %#v\n", s3, s3, s3)

    // 方式4
    s4 := &Student{} // == new(Student)
    fmt.Printf("%p %T %#v\n", s4, s4, s4)

    var s5 Student
    fmt.Printf("%T %#v\n", s5, s5)
}

输出

0xc0000221b0 *main.Student &main.Student{name:"", age:0, city:""}
0xc000022210 *main.Student &main.Student{name:"", age:0, city:""}
0xc000022270 *main.Student &main.Student{name:"", age:0, city:""}
0xc0000222d0 *main.Student &main.Student{name:"", age:0, city:""}
main.Student main.Student{name:"", age:0, city:""}

值传递和指针传递

type Student struct {
    name string
    age  int
    city string
}

func setAge1(s Student) {
    s.age = 30
}

func setAge2(s *Student) {
    s.age = 30
}

func main() {
    s1 := Student{"mike", 18, "beijing"}
    setAge1(s1)     // 值传递
    fmt.Println(s1) // {mike 18 beijing}
    setAge2(&s1)    // 指针传递
    fmt.Println(s1) // {mike 30 beijing}

    s2 := &Student{"john", 18, "beijing"}
    setAge1(*s2)    // 值传递
    fmt.Println(s2) // &{john 18 beijing}
    setAge2(s2)     // 指针传递
    fmt.Println(s2) // &{john 30 beijing}
}

构造函数

func NewStudent(name string, age int, city string) *Student {
    return &Student{
        name: name,
        age:  age,
        city: city,
    }
}

func main() {
    s1 := NewStudent("mike", 18, "beijing")
    fmt.Printf("%#v\n", s1) // &main.Student{name:"mike", age:18, city:"beijing"}
}

方法

声明格式

func (接收者变量 接收者类型) 方法名(参数列表) (返回值列表) {
    函数体
}

普通函数
func 函数名(参数列表) (返回值列表){
    函数体
}

值类型和指针类型的接收者

// 值类型的接收者
func (s Student) SetAge1(newAge int) {
    s.age = newAge
}

// 指针类型的接收者
func (s *Student) SetAge2(newAge int) {
    s.age = newAge
}

func main() {
    // 值类型
    s2 := Student{
        name: "john",
        age:  18,
        city: "shanghai",
    }

    // 指针类型
    s3 := &Student{
        name: "jack",
        age:  18,
        city: "guangzhou",
    }

    // 方法
    // Go 有一个 语法糖:方法调用时,编译器会自动在值和指针之间转换
    s2.SetAge1(20)          // 值调用
    fmt.Printf("%#v\n", s2) // main.Student{name:"john", age:18, city:"shanghai"}
    s2.SetAge2(30)          // 值调用,Go 会自动取地址 &s2 转换为指针调用
    fmt.Printf("%#v\n", s2) // main.Student{name:"john", age:30, city:"shanghai"}

    s3.SetAge1(20)          // 指针调用
    fmt.Printf("%#v\n", s3) // &main.Student{name:"jack", age:18, city:"guangzhou"}
    s3.SetAge2(30)          // 指针调用,Go 会自动取值 *s3 转换为值调用
    fmt.Printf("%#v\n", s3) // &main.Student{name:"jack", age:30, city:"guangzhou"}
}

嵌套结构体

type Adress struct {
    province string
    city     string
}

type Person1 struct {
    name   string
    gender string
    age    int
    adress Adress
}

func main() {
    p2 := Person1{
        name: "mike",
        adress: Adress{
            province: "fujian",
            city:     "fuzhou",
        },
    }
    fmt.Printf("%#v\n", p2)
}