• 【go语言】方法


    go的方法是一种作用在接收者(某种类型的变量,不能是接口和指针)上的特殊函数

    方法的声明

    // 类型方法接收者是值类型
    func (t TypeName) MethodName (ParamList ) (Returnlist) {
    	//method body
    }
    
    // 类型方法接收者是指针
    func (t *TypeName) MethodName (ParamList) (Returnlist) {
    	//method body
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    t 是接收者或者叫接收器变量,官方建议使用接收器类型名 TypeName 的 第一个小写字母,而不是 self 、 this 之类的命名。

    TypeName 为命名类型的类型名;

    MethodName 为方法名,是一个自定义标识符;

    ParamList 是形参列表;

    ReturnList 是返回值列表;

    //结构体方法
    type twonum struct{
        a int
        b int
    }
    func (tn*twonum) add() int{
        return tn.a+tn.b
    }
    //切片方法
    type IntVector []int
    func(v IntVector)sum()(s int){
        for _,x:=range v{
            s+=x
        }
        return s
    }
    func main(){
        two:=twonum{2,4}
        fmt.Println(two.add())
        arr:=IntVector{1,2,3,4,5}
    	fmt.Println(arr.Sum())
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述
    在这里插入图片描述

    注意事项

    方法的receiver type并非一定要是struct类型,type定义的类型别名、slice、map、channel、func类型等都可以。但内置简单数据类型(int、float等)不行,interface类型不行。

    在这里插入图片描述

    Go中没有 方法重载 的说法,也就是说同一个类型中的所有方法名必须都唯一。但不同类型中的方法,可以重名

    type定义类型的别名时,别名类型不会拥有原始类型的方法。例如mytype上定义了方法add(),mytype的别名new_type不会有这个方法,除非自己重新定义。

    值类型的receiver和指针类型的receiver

    type person struct{
        name string
        age int
    }
    
    • 1
    • 2
    • 3
    • 4

    有两种类型的实例:

    p1 := new(person)
    p2 := person{}
    
    • 1
    • 2

    p1是指针类型的person实例,p2是值类型的person实例。在需要访问或调用person实例属性时候,如果发现它是一个指针类型的变量,Go会自动将其解除引用,所以p1.name在内部实际上是(*p1).name。同理,调用实例的方法时也一样,有需要的时候会自动解除引用。

    除了实例有值类型和指针类型的区别,方法也有值类型的方法和指针类型的区别,也就是以下两种receiver:

    func (p person) setname(name string) { 
        p.name = name 
    }
    func (p *person) setage(age int) {
        p.age = age 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    setname()方法中是值类型的receiver,setage()方法中是指针类型的receiver。它们是有区别的。

    首先,setage()方法的p是一个指针类型的person实例,所以方法体中的p.age实际上等价于(*p).age。

    方法就是函数,Go中所有需要传值的时候,都是按值传递的,也就是拷贝一个副本。

    setname()中,除了参数name需要拷贝,receiver部分(p person)也会拷贝,而且它明确了要拷贝的对象是值类型的实例,也就是拷贝完整的person数据结构。但实例有两种类型:值类型和指针类型。(p person)无视它们的类型,因为receiver严格规定p是一个值类型的实例。所以无论是指针类型的p1实例还是值类型的p2实例,都会拷贝整个实例对象。对于指针类型的实例p1,Go会自动解除引用,所以p1.setname()等价于(*p1).setname()。

    也就是说,只要receiver是值类型的,无论是使用值类型的实例还是指针类型的实例,都是拷贝整个底层数据结构的,方法内部访问的和修改的都是实例的副本。所以,如果有修改操作,不会影响外部原始实例。

    setage()中,receiver部分(p *person)明确指定了要拷贝的对象是指针类型的实例,无论是指针类型的实例p1还是值类型的p2,都是拷贝指针。所以p2.setage()等价于(&p2).setage()。

    也就是说,只要receiver是指针类型的,无论是使用值类型的实例还是指针类型的实例,都是拷贝指针,方法内部访问的和修改的都是原始的实例数据结构。所以,如果有修改操作,会影响外部原始实例。

    嵌套在struct中的方法,匿名字段

    当内部struct嵌套进外部struct时,外部struct就有了内部struct的方法

    请看下面的例子

    type person struct{}
    
    func (p *person) speak() {
    	fmt.Println("person speak")
    }
    type Student struct {
    	person
    	a int
    }
    func main() {
    	stu := new(Student)
    	// 直接调用内部struct的方法
    	stu.speak()
    	// 间接调用内部stuct的方法
    	stu.person.speak()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    如果Student也有一个名为speak()的方法,那么Student的speak()方法将掩盖内部person的speak()方法。所以stu.speak()调用的将是属于Admin的speak(),而stu.preson.speak()将调用的是person的speak()。

    type person struct{}
    
    func (p *person) speak() {
    	fmt.Println("person speak")
    }
    type Student struct {
    	person
    	a int
    }
    func (s *Student) speak(){
        fmt.Println("student speak")
    }
    func main() {
    	stu := new(Student)
    	stu.speak()
    	stu.person.speak()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    嵌套在struct中的方法,非匿名字段

    将另一个struct作为外部struct的一个命名字段。

    type person struct {
        name string
        age int
    }
    type Student struct {
        people *person
        score int
    }
    func (p *person) speak() {
    	fmt.Println("person speak")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    多重继承

    因为Go的struct支持嵌套多个其它匿名字段,所以支持"多重继承"。这意味着外部struct可以从多个内部struct中获取属性、方法。

    一个非常典型的例子就是照相手机cameraPhone是一个struct,其内嵌套Phone和Camera两个struct,那么cameraPhone就可以获取来自Phone的call()方法进行拨号通话,获取来自Camera()的takeAPic()方法进行拍照。

  • 相关阅读:
    Java21 + SpringBoot3使用Spring Security时如何在子线程中获取到认证信息
    批量测试ip连通性shell脚本
    Bluez目录结构分析
    Jquery,javascript 的处理机制
    【附源码】Python计算机毕业设计视频网站
    灵活好用的sql monitoring 脚本 part5
    基于动态规划法的水力发电优化调度(Python代码实现)
    ctfshow-web-红包题 辟邪剑谱
    分享一个基于python+爬虫的豆瓣电影数据可视化分析系统源码
    Python量化接口源码分享
  • 原文地址:https://blog.csdn.net/m0_72895175/article/details/133546333