美文网首页
2023-11-09(go方法)

2023-11-09(go方法)

作者: 护念 | 来源:发表于2023-11-08 22:40 被阅读0次

今日概述

最近几天没来写日志,有点懈怠,今天开始总结下go的方法知识点。

1. 方法和函数的区别

  1. 方法有一个接收者对象(定义时显示写出来)
  2. 对于方法而言,值/指针调用编译器会自动转换成接收者的类型可以混用;但是函数不行—关键点。

比如:

package main

import "fmt"

type Person struct {
    name string
    age  int
}

// 值接收者
func (p Person) Hello() {
    fmt.Println("Hello")
}

// 指针接收者
func (p *Person) Welcome() {
    fmt.Println("welcome")
}

// 函数 这个时候只能输入 值
func FunHello(name string) {
    fmt.Println(name)
}

func main() {
    p := Person{"张数", 12}

    // 值/指针都可以调用
    p.Hello()
    (&p).Hello()

    p.Welcome()
    (&p).Welcome()

    name := "dmy"
    FunHello(name)
    //FunHello(&name) cannot use &name (value of type *string) as string value in argument to FunHello
}

2. 结构体匿名字段-结构体方法提升

在上述情况下,字段结构体的方法会提升到当前结构体可用。

package main

import "fmt"

type Human struct {
    work string
}

func (h *Human) WorkInfo() {
    fmt.Printf("work info: %v\n", h.work)
}

type Person struct {
    name  string
    age   int
    Human // 等同于字段名也是 Human Human的方法会提升
}

func (p *Person) Name() {
    fmt.Printf("My name: %v\n", p.name)
}

func main() {
    p := Person{
        name:  "张三",
        age:   12,
        Human: Human{work: "cleaner"}, // 虽然混合这里要分开写
    }

    // 此时person同时有了Person和Human的方法
    p.Name()
    p.WorkInfo()
}

3. 表达式

我的简单理解是,它可以用于将方法暂时不执行,留着后续执行;
它有两种:

  1. 方法值(这种封装了方法对象在里面)
  2. 方法表达式值(这种没有封装对象,执行是需要传参进入)
package main

import "fmt"

type Person struct {
    name string
    age  int
}

func (p *Person) Name() {
    fmt.Printf("My name: %v\n", p.name)
}

func (p Person) Age() {
    fmt.Printf("My age: %v\n", p.age)
}

func main() {
    p := Person{
        name: "张三",
        age:  12,
    }

    // 方法值表达式
    Val := p.Name
    Val() // 内部封装了对象p

    // 方法表达式
    exp := Person.Age
    exp(p) // 内部没有封装对象p所以要传
}

另外一点区别是,对于表达式,如果是指针接收者,则写的时候必须严格按照指针写。

举例说明:

package main

import "fmt"

type Person struct {
    name string
    age  int
}

func (p *Person) Name() {
    fmt.Printf("My name: %v\n", p.name)
}

func (p Person) Age() {
    fmt.Printf("My age: %v\n", p.age)
}

func main() {
    p := Person{
        name: "张三",
        age:  12,
    }

    // 方法表达式 - 此时写随便写都行
    exp := Person.Age
    exp(p) // 内部没有封装对象p所以要传

    // 这里改成指针 也没问题
    exp1 := (*Person).Age
    exp1(&p)

    // 如果是指针类型则只能指针
    exp2 := (*Person).Name
    exp2(&p)

    // 报错
    // exp3 := Person.Name
    // exp3(p) // invalid method expression Person.Name (needs pointer receiver (*Person).Name)
}

4. 一点特别的说明

  1. nil可以转换成指针类型
  2. 但是nil 不能转换成值类型
package main

type Data struct{}

func (Data) TestValue() {}

func (*Data) TestPointer() {}

func main() {
    var p *Data = nil
    p.TestPointer()

    // 这里是将 nil 转换成 *Data类型
    (*Data)(nil).TestPointer() // method value
    (*Data).TestPointer(nil)   // method expression

    // p.TestValue()            // invalid memory address or nil pointer dereference

    // (Data)(nil).TestValue()  // cannot convert nil to type Data
    // Data.TestValue(nil)      // cannot use nil as type Data in function argument
}

相关文章

  • 第04天(面对对象编程)_03

    11_方法的继承.go 12_方法的重写.go 13_方法值.go 14_方法表达式.go 15_接口的定义和实现.go

  • 2023-11-09

    别让生活蒙蔽了你 这个快节奏的社会中,人们往往面临着各种压力和困惑,生活中...

  • golang系列教程

    Go包管理 Go开发工具 Go Doc 文档 Go 数组 Go 切片 Go Map Go 类型 Go 函数方法 G...

  • 21. Go 协程

    21. Go 协程 Go 协程是什么? Go 协程是与其他函数或方法一起并发运行的函数或方法。Go 协程可以看作是...

  • go语言中的方法

    go支持OO语言的一些特性,方法就是其中之一。本文将介绍go语言中方法相关的概念。 方法声明 在go语言中,我们可...

  • 2021-03-04 - 2

    执行方法1 go build 执行代码的路径 例如 :go build /Users/apple/go/src/g...

  • go语言array, slice, map(四)

    array go语言数组,定义方法如下: var arr [n]type 声明方法 go语言也支持多维数组 sli...

  • go test相关命令记录

    1.执行单个*_test.go文件下的所有方法 go test -v demo_test.go demo.go 2...

  • 博士「快毕业」的方法

    原文链接:博士「快毕业」的方法 To go, or not to go. 莎士比亚写下了“to be or not...

  • go 方法

    Go 既允许使用值,也允许使用指针来调用方法,不必严格符合接收者的类型。

网友评论

      本文标题:2023-11-09(go方法)

      本文链接:https://www.haomeiwen.com/subject/yltcwdtx.html