Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, func 。
 
相比 Java,Python,Javascript 等引用类型的语言,Golang 拥有类似C语言的指针这个相对古老的特性。但不同于 C 语言,Golang 的指针是单独的类型,而不是 C 语言中的 int 类型,而且也不能对指针做整数运算。从这一点看,Golang 的指针基本就是一种引用。
 
那么 Golang 为什么需要指针?这种指针又能有什么独特的用途呢?
 
在学习引用类型语言的时候,总是要先搞清楚,当给一个函数/方法传参的时候,传进去的是值还是引用。实际上,在大部分引用型语言里,参数为基本类型时,传进去的大都是值,也就是另外复制了一份参数到当前的函数调用栈。参数为高级类型时,传进去的基本都是引用。这个主要是因为虚拟机的内存管理导致的。
 
内存管理中的内存区域一般包括 heap 和 stack, stack 主要用来存储当前调用栈用到的简单类型数据:string,boolean,int,float 等。这些类型的内存占用小,容易回收,基本上它们的值和指针占用的空间差不多,因此可以直接复制,GC也比较容易做针对性的优化。 复杂的高级类型占用的内存往往相对较大,存储在 heap 中,GC 回收频率相对较低,代价也较大,因此传引用/指针可以避免进行成本较高的复制操作,并且节省内存,提高程序运行效率。
 
因此,在下列情况可以考虑使用指针:1,需要改变参数的值;2,避免复制操作;3,节省内存;
 
而在 Golang 中,具体到高级类型 struct,slice,map,也各有不同。实际上,只有 struct 的使用有点复杂,slice,map,chan 都可以直接使用,不用考虑是值还是指针。
 
 
struct:
 
对于函数(function),由函数的参数类型指定,传入的参数的类型不对会报错,例如:
 
func passValue(s struct){}

func passPointer(s *struct){}
对于方法(method),接收者(receiver)可以是指针,也可以是值,Golang 会在传递参数前自动适配以符合参数的类型。也就是:如果方法的参数是值,那么按照传值的方式 ,方法内部对struct的改动无法作用在外部的变量上,例如:
 
package main

import "fmt"

type MyPoint struct {
X int
Y int
} func printFuncValue(p MyPoint){
p.X = 1
p.Y = 1
fmt.Printf(" -> %v", p)
} func printFuncPointer(pp *MyPoint){
pp.X = 1 // 实际上应该写做 (*pp).X,Golang 给了语法糖,减少了麻烦,但是也导致了 * 的不一致
pp.Y = 1
fmt.Printf(" -> %v", pp)
} func (p MyPoint) printMethodValue(){
p.X += 1
p.Y += 1
fmt.Printf(" -> %v", p)
} // 建议使用指针作为方法(method:printMethodPointer)的接收者(receiver:*MyPoint),一是可以修改接收者的值,二是可以避免大对象的复制
func (pp *MyPoint) printMethodPointer(){
pp.X += 1
pp.Y += 1
fmt.Printf(" -> %v", pp)
} func main(){
p := MyPoint{0, 0}
pp := &MyPoint{0, 0} fmt.Printf("\n value to func(value): %v", p)
printFuncValue(p)
fmt.Printf(" --> %v", p)
// Output: value to func(value): {0 0} -> {1 1} --> {0 0} //printFuncValue(pp) // cannot use pp (type *MyPoint) as type MyPoint in argument to printFuncValue //printFuncPointer(p) // cannot use p (type MyPoint) as type *MyPoint in argument to printFuncPointer fmt.Printf("\n pointer to func(pointer): %v", pp)
printFuncPointer(pp)
fmt.Printf(" --> %v", pp)
// Output: pointer to func(pointer): &{0 0} -> &{1 1} --> &{1 1} fmt.Printf("\n value to method(value): %v", p)
p.printMethodValue()
fmt.Printf(" --> %v", p)
// Output: value to method(value): {0 0} -> {1 1} --> {0 0} fmt.Printf("\n value to method(pointer): %v", p)
p.printMethodPointer()
fmt.Printf(" --> %v", p)
// Output: value to method(pointer): {0 0} -> &{1 1} --> {1 1} fmt.Printf("\n pointer to method(value): %v", pp)
pp.printMethodValue()
fmt.Printf(" --> %v", pp)
// Output: pointer to method(value): &{1 1} -> {2 2} --> &{1 1} fmt.Printf("\n pointer to method(pointer): %v", pp)
pp.printMethodPointer()
fmt.Printf(" --> %v", pp)
// Output: pointer to method(pointer): &{1 1} -> &{2 2} --> &{2 2}
}
slice :
 
slice 实际上相当于对其依附的 array 的引用,它不存储数据,只是对 array 进行描述。因此,修改 slice 中的元素,改变会体现在 array 上,当然也会体现在该 array 的所有 slice 上。
可以使用 make([]int) 来创建并初始化 map 。
 
 
map :
 
使用 make(map[string]string) 返回的本身是个引用,可以直接用来操作:
 
map["name"]="Jason";

而如果使用 map 的指针,反而会产生错误:

*map["name"]="Jason"  //  invalid indirect of m["title"] (type string)
(*map)["name"]="Jason" // invalid indirect of m (type map[string]string)
 
chan :
 
make(chan int) 返回的是可以直接使用的 channel 。
 
 
func :
 
在 Golang 中,func 可以作为一种值被返回,因此也可以使用类似 Python 的 decorator 的方式来加工函数。
 

go语言学习--指针的理解的更多相关文章

  1. c语言函数指针的理解与使用(学习)

    1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: 1 2 3 A) char * (*fun1)(char * p1,char * p2); B) char  ...

  2. c语言函数指针的理解与使用

    1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: A) char * (*fun1)(char * p1,char * p2); B) char * *fun ...

  3. go语言学习--指针数组和数组指针

    数组指针(也称行指针)定义 int (*p)[n];()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长.也就是说执行p+1时,p要跨过n个整型数据的 ...

  4. 转·c语言函数指针的理解与使用

    原文出处:https://www.cnblogs.com/haore147/p/3647262.html 1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: 1 ...

  5. Go语言学习——指针、new和make

    指针 Go语言中不存在指针操作,只需要记住两个符号: &:取地址 *:根据地址取值 vscode 打开多个标签页 settings.json中输入"workbench.editor. ...

  6. c语言学习-指针探究

    1:指针定义格式:格式:变量类型 *变量名用途:指针变量用于储存地址(only),也就是根据地址值,访问对应的存储空间. 注意.int *p 只能指向int类型的数据: 例: int a = 20; ...

  7. 大一C语言学习笔记(7)---指针篇--什么是指针?什么是指针变量?取地址符“&”的作用是什么?地址运算符“*”的作用是什么,怎么理解两者?

    "指针是C语言的灵魂"这句话一开始我没怎么明白,现在接触了指针,终于知道为什么这么说了,因为....难,真难:下面说一下我对这句话的见解: C语言拥有着其他语言所没有的特性---直 ...

  8. 说说对C语言指针的理解

    指针困扰了一些学习编程的人,或许你的老师会告诉你,指针比较难理解. 我当时被老师的话唬住所以学习指针那章的时候都没心情听课.(说得像讲别的内容时我听了似的,开玩笑) 导致了学习链表的时候各种卧槽. * ...

  9. C语言一维指针的深入理解

    指针是C语言中广泛使用的一种数据类型.运用指针编程是C语言最主要的风格之一. 利用指针变量可以表示各种数据结构:能很方便地使用数组和字符串:并能象汇编语言一样处理内存地址,从而编出精练而高效的程序.指 ...

随机推荐

  1. mac-ppt-auto-open-recovery-files

    mac 每次打开PPT都会出现一个自动保存的文件,不知道这个文件是保存在哪里,该怎么删除 打开finder(访达),按 shift+command+G,输入~/Library/Containers/c ...

  2. Modularizing your graphQL schemas

    转自: https://tomasalabes.me/blog/nodejs/graphql/2018/07/11/modularizing-graphql.html Modularizing you ...

  3. redis服务以及phpredis扩展的安装

    一.下载软件包 下载redis wget http://download.redis.io/releases/redis-3.0.7.tar.gz 下载redis的php扩展 wget http:// ...

  4. HTTP redirect 重定向到 HTTPS

    最近帮一个顾客做网站,  需要HTTPS. 之前接触的SSL certificate直接上传到plesk 上面勾选重定向即可. 在此先吐槽下godaddy 服务贵功能还少. 用代码从HTTP来重定向到 ...

  5. AD10 没有原理图是否可以修改 PCB

    AD10 没有原理图是否可以修改 PCB 有朋友问 AD 是否可以在没有原理的情况下修改 PCB 呢? 答案是肯定的,可以. 比如增加元件和网络,可以先增加元件封装,再打开网络管理给焊盘加上网络. 相 ...

  6. 论 大并发 下的 乐观锁定 Redis锁定 和 新时代事务

    在 <企业应用架构模式> 中 提到了 乐观锁定, 用 时间戳 来 判定 交易 是否有效, 避免 传统事务 的 表锁定 造成 的 瓶颈 . 在 现在的 大并发 的 大环境下, 传统事务 及其 ...

  7. TypeScript 之 函数

    https://m.runoob.com/manual/gitbook/TypeScript/_book/doc/handbook/Functions.html 为函数定义类型 为函数添加类型: fu ...

  8. 修改ORA-28001 口令已经失效问题

    Oracle默认密码的有效时间为180天,当超过180天时,将出现如下错误 解决方法: 使用Oracle SQL Developer登录Oralce, 以as sysdba登录 登录后,执行 sele ...

  9. Linux 高级文本处理命令

    1.2.1 cut命令 cut命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields     ## 用于有特定分隔字符 [ ...

  10. RedHat6.5安装zookeeper集群

    版本号: Redhat6.5  zookeeper-3.4.6  JDK1.8 zookeeper下载 官网下载地址:https://mirrors.tuna.tsinghua.edu.cn/apac ...