Golang 方法笔记

Golang中的方法是作用在指定的数据类型上的,因此自定义类型都可以有方法。

方法定义

func (recevier type) methodName (参数列表) (返回值列表) {

方法体

return 返回值

}

基本申明和调用

type A struct {

Num int

}

func (a A) test() {

fmt.Println(a.Num)

}

说明:func (a A) test() 表示结构体A有一个test的方法

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// 定义一个方法
func (p Person) Talk() {
    fmt.Println(p.Name)
}

func main() {
    var person1 = Person{
        Name: "宋江",
        Age:  20,
    }
    person1.Talk()
}

方法中指针的使用

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// 给Person结构体定义一个方法
func (p *Person) Talk() { // *Person 表示传递参数为指针
    p.Name = "卢俊义"
    // 指针标准写法
    fmt.Println("Talk(),Name=", (*p).Name)
    // 省略写法
    fmt.Println("Talk(),Name=", p.Name)
}

func main() {
    var person1 = Person{
        Name: "宋江",
        Age:  20,
    }
    person1.Talk()
    fmt.Println("main(),Name=", person1.Name) // 指针修改了值,所以输出:卢俊义
}

方法中使用内置类型

package main

import "fmt"

type integer int // 给内置类型指定别名

func (i *integer) change() {
    *i++ // 这里的*不能省略
}

func main() {
    var i integer = 10
    i.change()
    fmt.Println(i)
}

指针默认调用String()

package main

import "fmt"

type Student struct {
    Name string
    Age  int
}

func (stu *Student) String() string {
    s := fmt.Sprintf("Name=[%v], Age=[%v]", stu.Name, stu.Age)
    return s
}

func main() {
    stu := Student{
        Name: "宋江",
        Age:  20,
    }
    fmt.Println(stu)
    fmt.Println(&stu) // 指针会自动调用String()
}

方法和函数的不同点

  • 调用方式不同

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

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

  • 对于普通函数,接受者为值类型时不能传递指针类型;接受者为指针时不能传递值类型

package main

import "fmt"

type Student struct {
    Name string
}

// 定义接受值类型函数,只能传递值类型
func Speak(stu Student) string {
    return stu.Name
}

// 定义接受指针类型函数,只能指针类型
func Speak2(stu *Student) string {
    stu.Name = "卢俊义" // 此处为省略写法,标准写法为:(*stu).Name = "卢俊义"
    return stu.Name
}

func main() {
    stu := Student{
        Name: "宋江",
    }
    fmt.Println(Speak(stu)) // 只能传递值类型
    fmt.Println(stu.Name)
    fmt.Println(Speak2(&stu)) // 只能传递指针类型
    fmt.Println(stu.Name)
}
  • 对于方法(如struct的方法),接受者为值类型时可以用传递指针类型;接受者为指针时也可以传递值类型

package main

import "fmt"

type Student struct {
    Name string
}

// Student结构体的方法,值传递可以是值类型,也可以是指针
func (stu Student) Speak() string {
    s := fmt.Sprintf("Name=[%v]", stu.Name)
    return s
}

// Student结构体的方法,值传递可以是值类型,也可以是指针
func (stu *Student) Speak2() string {
    stu.Name = "卢俊义"
    s := fmt.Sprintf("Name=[%v]", stu.Name)
    return s
}

func main() {
    stu := Student{
        Name: "宋江",
    }
    fmt.Println(stu.Speak())
    fmt.Println((&stu).Speak()) // 传递指针也可以。此处注意,虽然传递的是指针,但stu.Name并不会改变!!!
    fmt.Println(stu.Name)
    fmt.Println(stu.Speak2()) // 传递值类型也可以
    fmt.Println((&stu).Speak2())
    fmt.Println(stu.Name) // 由于执行了Speak2()指针方法,因此Name改为:卢俊义
}

总结

  1. 不管调用方式如何,真正决定是指拷贝还是地址拷贝,看这个方法是和哪个类型绑定

  1. 如果是和值类型绑定,如:(str Student),则是值拷贝;如:(str *Student),则是地址拷贝

  1. 地址拷贝会修改原定义值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值