Go语言方法规则

幸运草 2020年4月23日22:04:29函数代码评论阅读模式

Go语言方法规则

根据调用者不同,方法分为两种表现形式:方法(method value)、方法表达式(method expression)。

两者都可像普通函数那样赋值和传参,区别在于 方法 (method value)绑定了实例,而方法表达式(method expression)必须显式传参。

直接调用

直接调用,类型 T 和 *T 上的方法集是互相继承的。

package main

import (
    "fmt"
)

type T struct {
    int
}

func (t T) testT() {
    fmt.Println("接受者为 T ")
}

func (t *T) testP() {
    fmt.Println("接受者为 *T ")
}

func main() {
    t1 := T{1}
    fmt.Printf("t1 is : %vn", t1)
    t1.testT()
    t1.testP()

    t2 := &t1
    fmt.Printf("t2 is : %vn", t2)
    t2.testT()
    t2.testP()
}

直接调用,类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 T 和 *T 上的方法集是互相继承的。

package main

import (
    "fmt"
)

type ST struct {
    T
}

type SP struct {
    *T
}

type T struct {
    int
}

func (t T) testT() {
    fmt.Println("类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 T 方法")
}
func (t *T) testP() {
    fmt.Println("类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 *T 方法")
}

func main() {
    st1 := ST{T{1}}
    st2 := &st1
    fmt.Printf("st1 is : %vn", st1)
    st1.testT()
    st1.testP()
    fmt.Printf("st2 is : %vn", st2)
    st2.testT()
    st2.testP()

    sp1 := SP{&T{1}}
    sp2 := &sp1
    fmt.Printf("sp1 is : %vn", sp1)
    sp1.testT()
    sp1.testP()
    fmt.Printf("sp2 is : %vn", sp2)
    sp2.testT()
    sp2.testP()
}

隐式传递调用

接受者隐式传递,类型 T 和 *T 上的方法集是互相继承的。

package main

import (
    "fmt"
)

type T struct {
    string
}

func (t T) testT() {
    fmt.Println("接受者为 T ")
}

func (t *T) testP() {
    fmt.Println("接受者为 *T ")
}

func main() {
    t := T{"oldboy"}
    methodValue1 := t.testT
    methodValue1()
    methodValue2 := (&t).testT
    methodValue2()
    methodValue3 := t.testP
    methodValue3()
    methodValue4 := (&t).testP
    methodValue4()
}

接受者隐式传递,类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 T 和 *T 上的方法集是互相继承的。

package main

import (
    "fmt"
)

type ST struct {
    T
}

type SP struct {
    *T
}

type T struct {
    string
}

func (t T) testT() {
    fmt.Println("类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 T 方法")
}
func (t *T) testP() {
    fmt.Println("类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 *T 方法")
}

func main() {
    st1 := ST{T{"oldboy"}}
    methodValue1 := st1.testT
    methodValue1()
    methodValue2 := (&st1).testT
    methodValue2()
    methodValue3 := st1.testP
    methodValue3()
    methodValue4 := (&st1).testP
    methodValue4()

    sp1 := SP{&T{"oldboy"}}
    methodValue5 := sp1.testT
    methodValue5()
    methodValue6 := (&sp1).testT
    methodValue6()
    methodValue7 := sp1.testP
    methodValue7()
    methodValue8 := (&sp1).testP
    methodValue8()
}

显式传递调用

接受者显示传值,类型 T 的可调用方法集包含接受者为 T 的所有方法,不包含接受者为 *T 的方法。类型 *T 的可调用方法集包含接受者为 *T 或 T 的所有方法集。

package main

import (
    "fmt"
)

type T struct {
    string
}

func (t T) testT() {
    fmt.Println("接受者为 T ")
}

func (t *T) testP() {
    fmt.Println("接受者为 *T ")
}

func main() {
    t := T{"oldboy"}
    expression1 := T.testT
    expression1(t)
    expression2 := (*T).testT
    expression2(&t)

    // expression3 := T.testP
    // expression3(t)
    expression4 := (*T).testP
    expression4(&t)

}

接受者显示传值,类型 S 包含匿名字段 *T ,则 S 和 *S 方法集包含 T 和 *T 上的方法集是互相继承的。
类型 S 包含匿名字段 T ,类型 S 的可调用方法集包含接受者为 T 的所有方法,不包含接受者为 *T 的方法。类型 *S 的可调用方法集包含接受者为 *T 或 T 的所有方法集。

package main

import (
    "fmt"
)

type ST struct {
    T
}

type SP struct {
    *T
}

type T struct {
    string
}

func (t T) testT() {
    fmt.Println("类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 T 方法")
}
func (t *T) testP() {
    fmt.Println("类型 S 包含匿名字段 *T 或 T ,则 S 和 *S 方法集包含 *T 方法")
}

func main() {
    st1 := ST{T{"oldboy"}}
    expression1 := ST.testT
    expression1(st1)
    expression2 := (*ST).testT
    expression2(&st1)
    // expression3 := ST.testP
    // expression3(st1)
    expression4 := (*ST).testP
    expression4(&st1)

    sp1 := SP{&T{"oldboy"}}
    expression5 := SP.testT
    expression5(sp1)
    expression6 := (*SP).testT
    expression6(&sp1)
    expression7 := SP.testP
    expression7(sp1)
    expression8 := (*SP).testP
    expression8(&sp1)
}

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 加入Q群
  • QQ扫一扫
  • weinxin
幸运草
Go语言中的常量 函数代码

Go语言中的常量

1 概述 常量,一经定义不可更改的量。功能角度看,当出现不需要被更改的数据时,应该使用常量进行存储,例如圆周率。从语法的角度看,使用常量可以保证数据,在整个运行期间内,不会被更改。例如当前处理器的架构...
Go语言的接口 函数代码

Go语言的接口

Go语言-接口 在Go语言中,一个接口类型总是代表着某一种类型(即所有实现它的类型)的行为。一个接口类型的声明通常会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干方法声明...
Go语言支持的正则语法 函数代码

Go语言支持的正则语法

1 字符 语法 说明 . 任意字符,在单行模式(s标志)下,也可以匹配换行 字符类 否定字符类 d Perl 字符类 D 否定 Perl 字符类 ASCII 字符类 否定 ASCII 字符类 pN U...
Go语言的包管理 函数代码

Go语言的包管理

1 概述 Go 语言的源码复用建立在包(package)基础之上。包通过 package, import, GOPATH 操作完成。 2 main包 Go 语言的入口 main() 函数所在的包(pa...

发表评论