几个比较绕人的概念好好理一下

概念

Go语言

  • 单独定义 函数
  • 为 结构体 添加函数,被添加方法的结构体的变量名在 Golang 中被叫做 接收器

Go语言中 接收器

  • 接收器 类型 可以是任何类型比如 int、bool、string、数组、切片 等类型的别名,甚至也可以是函数类型
  • 接收器不能是一个接口类型,接口是一个抽象定义,而方法却是具体实现,如果这样做会引发一个编译错误

结构体指针内部转换

  1. package main
  2. import "fmt"
  3. type person struct {
  4. name string //名字
  5. sex byte //性别, 字符类型
  6. age int //年龄
  7. }
  8. func (p person) setInfoValue() {
  9. fmt.Println("SetInfoValue")
  10. }
  11. func (p *person) setInfoPointer() {
  12. fmt.Println("SetInfoPointer")
  13. }
  14. func main() {
  15. p := &person{"mike", 'm', 18}
  16. (*p).setInfoPointer() // 把(*p)转换层p后再调用,等价于 p.setInfoValue()
  17. p.setInfoValue() // 内部做的转换, 先把指针p, 转成*p后再调用 (*p).setInfoValue()
  18. p2 := person{"tom", 'm', 18}
  19. p2.setInfoPointer() // 内部,先把p2转为为&p2再调用, (&p).setInfoPointer()
  20. // (&p2).setInfoPointer()
  21. p2.setInfoValue()
  22. }

为结构体添加方法

一般建议为值类型添加这样的方法

  1. var (s StructType)funcName(param1 param1Type, ...)(returnVal1 returnType1, ...){ }

为结构体 StructType 添加一个函数 funcName,该函数的参数为 param1,返回值为 returnVal1,参数和返回值可以有 0 个或者任意多个。

  1. package main
  2. import "fmt"
  3. type Student struct {
  4. Name string
  5. Age int
  6. Score float64
  7. }
  8. func (p Student)print(){
  9. fmt.Println("Name =", p.Name, "Age =", p.Age) //Name = Ueumd Age = 18
  10. }
  11. func (s Student)isPass(score float64)(isPass bool){
  12. if s.Score >= score{
  13. return true
  14. }
  15. return false
  16. }
  17. func main() {
  18. var p = Student{
  19. Name: "Ueumd",
  20. Age: 18,
  21. Score: 60,
  22. }
  23. p.print()
  24. isPass := p.isPass(100)
  25. fmt.Println("IsPass =",isPass) //IsPass = false
  26. /**
  27. Name = Ueumd Age = 18
  28. IsPass = false
  29. */
  30. }

为结构体添加方法指针接收器 (实例)

Go 语言 中 结构体 方法的接收器可以是一个 指针 类型。
如果是指针类型的接收器,那么在方法中,对结构体的修改都会生效。

  1. var (this *StructType)funcName(param1 param1Type, ...)(returnVal1 returnType1, ...){}

为结构体 StructType 添加一个 函数 funcName,该函数的 参数 为 param1,返回值 为 returnVal1,参数和返回值可以有 0 个或者任意多个。

this是一个指针接收器,可以通过 this 对结构体成员变量的修改。

使用指针接收器的方法,可以通过指针修改成员变量的值。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type Student struct {
  6. Name string
  7. Age int
  8. Score float64
  9. }
  10. func (p Student)print(){
  11. fmt.Println("Name =", p.Name, ", Age =", p.Age) //Name = Ueumd , Age = 18
  12. }
  13. func (s Student)isPass(score float64)(isPass bool){
  14. if s.Score >= score{
  15. return true
  16. }
  17. return false
  18. }
  19. func (this Student)setName2(name string) {
  20. this.Name = name
  21. }
  22. // 使用指针接收器的方法,可以通过指针修改成员变量的值
  23. func (this *Student)setName(name string) {
  24. this.Name = name
  25. }
  26. func main() {
  27. var p = Student{
  28. Name: "Ueumd",
  29. Age: 18,
  30. Score: 60,
  31. }
  32. p.print()
  33. isPass := p.isPass(100)
  34. fmt.Println("IsPass =",isPass) //IsPass = false
  35. /**
  36. Name = Ueumd , Age = 18
  37. IsPass = false
  38. */
  39. // 并没有改变结构体成员变量
  40. p.setName2("我是谁")
  41. p.print() // Name = Ueumd , Age = 18
  42. /**
  43. 指针接书器会改变结构中成员变量
  44. 所以我们可以利用这一点去实现oop
  45. */
  46. p.setName("who am i") // Name = who am i , Age = 18
  47. p.print()
  48. }

指针接收器与非指针接收器区别

  • 指针接收器 可以对成员变量进行修改
  • 非指针接收器 不可以对指针变量进行修改
  • 指针接收器和非指针接收器不可以重名

Should I define methods on values or pointers?

  1. func (s *MyStruct) pointerMethod() { } // method on pointer 结构体 数组 切片
  2. func (s MyStruct) valueMethod() { } // method on value 适合基本类型

任意类型添加方法

  1. //为内置类型 int 类型添加方法
  2. type MyInt int
  3. func (m MyInt)IntAbs()MyInt{
  4. if m >= 0{
  5. return m
  6. }
  7. return -m
  8. }
  9. func init() {
  10. var myInt MyInt = 10
  11. fmt.Println("IntAbs =", myInt.IntAbs()) // 10
  12. myInt = -10
  13. fmt.Println("IntAbs =", myInt.IntAbs()) // 10
  14. }