1、结构体声明

type 结构体名称 struct{
    field type
    field type
}

举例:

type Dog struct {
    Name  string
    Age   int
    Color string
}

  

2、结构体使用

2.1 直接声明

var dog Dog

2.2 {}

type Dog struct {
    Name  string
    Age   int
    Color string
}

func main() {
    dog := Dog{"来福", 3, "白色"}
    fmt.Printf("dog=%v\n", dog)
}

2.3 new()  

type Dog struct {
	Name  string
	Age   int
	Color string
}

func main() {
    dog := new(Dog)
    // dog是一个指针,因此标准的给字段赋值应该是(*dog).Name = "来福" (*dog).Age = 3 (*dog).Color = "白色"
    // go设计者为了程序员使用方便,底层会对dog.Name = "来福"进行处理,会给dog加上取值运算(*dog).Name = "来福"
    dog.Name = "来福"  // 等价于(*dog).Name = "来福"
    dog.Age = 3      // 等价于(*dog).Age = 3
    dog.Color = "白色" // 等价于(*dog).Color = "白色"
    fmt.Printf("dog=%v\n", *dog)
}

2.4 &

type Dog struct {
    Name  string
    Age   int
    Color string
}

func main() {
    dog := &Dog{"来福", 3, "白色"}
    fmt.Printf("dog=%v\n", *dog)
}

2.5 创建struct实例指定字段值 

type Person struct {
    Name string
    Age  int
}

func main() {
    person := Person{
	Name: "Tom",
	Age:  18,
    }

    personPor := &Person{
	Name: "Jack",
	Age:  20,
    }
    fmt.Println("person=", person)
    fmt.Println("personPor=", *personPor)
} 

第三种方式和第四种方式返回的是结构体指针,结构体指针访问字段的标准方式应该是:(*结构体指针).字段名,比如(*dog).Name = "来福"

 

3、方法的声明

func (recevier type) methodName(参数列表)(返回值列表){
    方法体
    return 返回值
}

参数列表,表示方法输入

recevier type:表示这个方法和type这个类型进行绑定,或者说该方法作用于type类型

recevier type:可以是结构体,也可以说是自定义类型。

recevier就是type类型的一个变量(实例)。

参数列表表示方法的输入

返回值列表,表示返回的值,可以是多个。

方法主体,表示为了实现某一功能代码块

return语句不是必须的

type Dog struct {
    Name  string
    Age   int
    Color string
}

// 给Dog类型绑定一个方法
func (d Dog) Eat(food string) {
    fmt.Printf("%v正在吃%v\n", d.Name, food)
}

func main() {
    d := Dog{
	Name:  "小花",
	Age:   3,
	Color: "花色",
    }
    // 调用方法
    d.Eat("骨头")
}

  

4、函数和方法的区别

调用方式不一样

函数的调用方式:函数名(实参列表)

方法的调用方式:变量.方法名(实参列表)

b. 对于普通函数,接收者是值类型时,不能将指针类型的数据直接传递

c. 对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变量调用方法

type Person struct {
    Name string
    Age  int
}

func (p Person) test() {
    p.Name = "Merry"
}

func (p *Person) test01() {
    p.Name = "Jack"
}

func main() {
    person := Person{
	Name: "Tom",
	Age:  18,
    }
    person.test()
    fmt.Println("name=", person.Name)
    (&person).test() // 从形式上是传入地址,但本质任然是值拷贝
    fmt.Println("name=", person.Name)
    person.test01() // 等价于(&person).test01() 从形式上是传入值类型,但本质任然是地址拷贝
    fmt.Println("name=", person.Name)
    (&person).test01()
    fmt.Println("name=", person.Name)
}

输出:

name= Tom
name= Tom
name= Jack
name= Jack

不管调用形式如何,真正决定是值拷贝还是地址拷贝,看这个方法是和那个类型绑定的

如果是和值类绑定型,比如: (p Person) test(),则是值拷贝

如果是和地址类型绑定,比如:func (p *Person) test01(),则是地址拷贝

posted on 2022-03-03 02:13  smile学子  阅读(88)  评论(0编辑  收藏  举报