go 语言的自动解引用

关于go语言编译器自动解引用

  • 值类型的实参调用形参为值类型的方法

  • 指针类型的实参调用形参为值类型的方法(会进行“自动解引用”)

  • 值类型的实参调用形参为指针类型的方法(会进行“自动取引用”)

  • 指针类型的实参调用形参为指针类型的方法

 

我们还是用代码来说明问题。

type node struct {
  Name string
  Next *node
}

// 用c语言翻译,
// void Say(node* n) { printf("%d\n", 123); }
func (n *node) Say() {
  fmt.Println(123)
}

// 用c语言翻译,
// void Say(node n) { printf("%d\n", 123); }
func (n node) Say2() {
  fmt.Println(2333)
}

func main() {
  n1 := &node{Name: "hui"}
  n1.Say()
  n1.Say2()    // Say2()是值接收器  (*n1).Say2()  go编译器为我们加上*  自动解引用

  n2 := node{Name: "hui"}
  n2.Say()     // Say()是指针接收器 (&n2).Say()  go编译器为我们加上&  自动取引用
  n2.Say2()
}

记住两点

  1. go语言只有值传递,指针也是值传递。

  1. 值类型接收器、指针类型接收器 可以理解为函数 的 一个形参。结合c语言如何做,对于c语言来说传值、传指针哪种会改变实参。

 

关键理解:当传递给方法的形参是一个值类型时(值类型接收器),原值的内容不会受到影响,因为值传递,传递进来的是原值的复制副本(形参是副本);相反,当方法的形参是一个指针类型时,原值的内容将可能受到影响,因为传递的是指针类型复制,虽然是复制但是指针中存储的地址仍然是实参的真实地址。

 

一个链表节点删除的例子

以链表节点删除问题为例,由于在go语言中都是参数都是值传递,所以在链表操作的时候不能直接操作形参来修改原来指针的内容,但可以修改其指向的内容为什么呢,用代码来解释

 

type node struct {
  Name string
  Next *node
}

func main() {
  n1 := &node{Name: "zgh"}
  n2 := &node{Name: "dev"}
  n3 := &node{Name: "devaaa"}
  n1.Next = n2
  n2.Next = n3
  n3.Next = nil
  ts(n2)

  data := make([]string, 0)
  for n1 != nil {
    data = append(data, n1.Name)
    n1 = n1.Next
  }
  fmt.Println(data)
}

func ts(n *node) {
  // 方式一: out: [hui dev devaaa]  不会删除
  n = n.Next  // 这里的n是一个指针的复制,此操作只会更改形参n指针的指向,不会更改实参的指向,如果想修改实参的指向,只能用方式二

  // 方式二: out: [hui devaaa]
  //*n = *n.Next  // 会更改实参,也就是被复制的指针

  // 方式三: out: [hui asada]
  // 这种方式会更改实参,为什么呢 因为这里go语言的编译器会为你加上*来解引用
  //n.Next= n.Next.Next  // 实际(*n).Next=
  //n.Name = "asada"     // 实际(*n).Name=
}

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值