【Go 基础】指针与标识符

变量是一种使用方便的占位符,用于引用计算机内存地址。Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址,如下示例说明如何获取一个变量的内存地址:

 var i int = 10
 // i 的地址是什么,&i
 fmt.Println("i的地址=", &i) // i的地址= 0xc00008a008

什么是指针?

一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。指针变量通常缩写为 ptr。

示例说明:

 var i int = 10
 var ptr *int = &i // ptr 是一个指针变量,ptr 的类型 *int,ptr 本身的值 &i
 fmt.Printf("ptr=%v\n", ptr) // ptr=0xc00008a008
 fmt.Printf("ptr 的地址=%v\n", &ptr) // ptr 的地址=0xc000084020
 fmt.Printf("ptr 指向的值=%v\n", *ptr) // ptr 指向的值=10

变量、指针和地址三者的关系是,每个变量都拥有地址,指针的值就是地址。

通过指针修改变量的值:

 var num int = 9
 fmt.Printf("num address = %v\n", &num) // num address = 0xc000018178

 var ptr *int
 fmt.Printf("num = %v \n", num) // num = 9
 ptr = &num
 *ptr = 10
 fmt.Printf("num = %v \n", num) // num = 10

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

对变量进行取地址操作使用&操作符,可以获得这个变量的指针变量。
指针变量的值是指针地址。
对指针变量进行取值操作使用*操作符,可以获得指针变量指向的原变量的值。

取地址操作符&和取值操作符是一对互补操作符,&取出地址,根据地址取出地址指向的值。

var a int = 300
var ptr *int = a // 错误 cannot use a (type int) as type *int in assignment
var ptr *int = &a

指针的数据类型不匹配:

var a int = 300
var ptr *float32 = &a //cannot use &a (type *int) as type *float32 in assignment

以下程序输出的内容是什么?

 var a int = 300
 var b int = 400
 var ptr *int = &a // ptr指针指向变量a的地址 824633819512
 fmt.Printf("&a=%d\n", &a) // &a=824633819512
 *ptr = 100 // a=100
 ptr = &b // ptr指针指向变量b的地址 824633819520
 fmt.Printf("&b=%d\n", &b) // &b=824633819520
 *ptr = 200 // b=200
 fmt.Printf("a=%d,b=%d,*ptr=%d\n", a, b, *ptr) // a=100,b=200,*ptr=200

值类型和引用类型

分类:
* 值类型:基本数据类型 int 系列, float 系列, bool, string 、数组和结构体 struct
* 引用类型:指针、slice 切片、map、管道 chaninterface 等都是引用类型。

区别:
* 值类型:变量直接存储值,内存通常在栈中分配。
* 引用类型:变量存储的是一个地址,这个地址对应的空间才真正存储数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由 GC 来回收。

Java函数中定义的一些基本类型的变量(8种)和对象的引用变量都是在函数的栈Stack内存中分配,堆Heap内存用于存放由new创建的对象和数组。

标识符

Go 对各种变量、方法、函数等命名时使用的字符序列称为标识符,凡是可以起名字的地方都叫标识符。
标识符的命名规则:
* 由 26 个英文字母大小写,0-9 ,_ 组成。
* 数字不可以开头。
* 严格区分大小写。
* 标识符不能包含空格。
* 下划线_本身在 Go 中是一个特殊的标识符,称为空标识符。可以代表任何其它的标识符,但是它对应的值会被忽略(比如:忽略某个返回值)。所以仅能被作为占位符使用,不能作为标识符使用。
* 不能以系统保留关键字作为标识符(一共有 25 个),比如 breakif 等等...

示例说明:

// Go中严格区分大小写,认为 num 和 Num 是不同的变量
 var num int = 10
 var Num int = 20
 fmt.Printf("num=%v Num=%v\n", num, Num) // num=10 Num=20

 //标识符不能包含空格
 //var ab c int = 30 // syntax error: unexpected int at end of statement

 var _ int = 40 // 错误 仅能作为占位符使用,不能直接用作标识符
 //fmt.Println(_) // cannot use _ as value

var if int = 10 // syntax error: unexpected if, expecting name
 var int int = 90
 fmt.Println(int) // 90

案例说明:

hello // 正确
hello12 // 正确
1hello // 错误 ,不能以数字开头 
h-b // 错误 ,不能使用 -
x h // 错误, 不能含有空格
h_4 // 正确
_ab // 正确
int // 正确,但不推荐使用,系统预定义标识符
float32 // 正确,但不推荐使用,系统预定义标识符
if // 错误,系统保留关键字
_  // 错误,仅能作为占位符使用,不能直接用作标识符
Abc // 正确

标识符命名的注意事项:

  • 包名:保持 package 的名字和目录保持一致,尽量采取有意义的包名,简短有意义,并且不能和标准库冲突,例如:fmt
  • 变量名、函数名、常量名,需要采用驼峰法。
  • 变量名、函数名、常量名小驼峰(首字母小写)表示私有的(只能在本包使用),大驼峰(首字母大写)表示公有的(可以被其他包访问),在 go 中没有publicprivateprotected等权限修饰符。

相关推荐

微信扫一扫,分享到朋友圈

【Go 基础】指针与标识符
返回顶部

显示

忘记密码?

显示

显示

获取验证码

Close