在大部分面向对象语言如C++、C#、Java,在函数传参数时除了基础值类型,对象是通过引用方式传递的。

然而,在Go语言中,除了map、slice和chan,所有类型(包括struct)都是值传递的。

那么,如何在函数外使用函数内处理后的变量呢?只能通过返回新变量吗?

不,可以使用指针

大部分面向对象语言都很少有用到指针的场景了,但是在Go语言中有大量的指针应用场景,要成为一名合格的Gopher,必须了解。

概念

每一个变量都会分配一块内存,数据保存在内存中,内存有一个地址,就像门牌号,通过这个地址就可以找到里面存储的数据。

指针就是保存这个内存地址的变量。

&
go runmystrmystrPmystr
*

在之前的代码的后面增加一句代码:

go runmystr
*

例如:

指针应用场景

在其他OOP语言中,大多数情况是不需要花太多时间操作指针的,如Java、C#,对象的引用操作都已经交给了虚拟机和框架。而Go经常会用到指针。原因主要有3个:

interface

接下来就分别介绍一下,期间会穿插一些简单的代码片段,您可以创建一个Go文件输入代码,运行体验一下。

函数中传递指针参数

Go语言都是值传递,例如:

结果:

i
if*int
*intinti&icount*countmaini

可以看到结果

i

Struct结构体指针类型方法

Go语言中给结构体定义方法

这样的方法不会改掉结构体变量内的字段值。 就算是结构体方法,如果不使用指针,方法内还是传递结构体的值。

现在我们改用指针类型定义结构体方法看看。

ChangeName*myStructmyStruct

再运行一次,可以看到打印出来的名字改变了。

当使用指针类型定义方法后,结构体类型的变量调用方法时会自动取得该结构体的指针类型并传入方法。

指针类型的接口实现

最近在某问答平台回答了一个Gopher的问题,大致内容是问为什么不能用结构体指针类型实现接口方法?

看一下代码

这段代码是无法编译通过的,会提示

myStructChangeNamefunc (m *myStruct) ChangeName(newName string)*myStructmyStruct

改一改

在调用SetName时,用&mystruct 替代 mystruct:

编译运行,成功。

为什么结构体类型实现的接口该结构体的指针类型也算实现了,而指针类型实现的接口,不算是该结构体实现了接口呢?

** 原因是,结构体类型定义的方法可以被该结构体的指针类型调用;而结构体类型调用该指针类型的方法时是被转换成指针,不是直接调用。**

&mystructChangeNameSayMyNamemystructSayMyNamemystructChangeName

到此Go语言指针类型的应用介绍差不多了。

总结一下:

  1. Go语言中指针非常常用,一定要掌握
  2. Go语言除了map、slice、chan其他都是值传递,引用传递一定要用指针类型
  3. 结构体类型定义方法要注意使用指针类型
  4. 接口实现方法时,用指针类型实现的接口函数只能算是指针类型实现的,用结构体类型实现的方法也作为是指针类型实现。

欢迎关注公众号《晓代码》,和大家一起学习编程吧!