从零学习 Go 语言(07):数据类型之指针

hello_wbm · · 801 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Hi,大家好呀,我是一个刚学习 Go 语言不久的新手,在入门 Golang 的这段时间里,我写了很多详细的学习笔记,很适合新手学习噢。这些文章已经发布在我的个人微信公众号里:《Go编程时光》里,今天开始将文章内容搬运到这里,希望有更多的人看到,给更的人带来帮助,但是这里文章会相对滞后,想获取最新文章,可以前往关注《Go编程时光》,请放心关注,这是一个纯分享的号,完全没有广告。 **系列导读 ** [从零学习 Go 语言(01):一文搞定开发环境的搭建](https://studygolang.com/articles/27365) [从零学习 Go 语言(02):学习五种变量创建的方法](https://studygolang.com/articles/27432) [从零学习 Go 语言(03):数据类型之整型与浮点型](https://studygolang.com/articles/27440) [从零学习 Go 语言(04):byte、rune与字符串](https://studygolang.com/articles/27463) [从零学习 Go 语言(05):数据类型之数组与切片](https://studygolang.com/articles/27508) [从零学习 Go 语言(06):数据类型之字典与布尔类型](https://studygolang.com/articles/27563) --- ## 0. 什么是指针 当我们定义一个变量 name ```go var name string = "Go编程时光" ``` 此时,name 是变量名,它只是编程语言中方便程序员编写和理解代码的一个标签。 当我们访问这个标签时,机算机会返回给我们它指向的内存地址里存储的值:`Go编程时光`。 出于某些需要,我们会将这个内存地址赋值给另一个变量名,通常叫做 ptr(pointer的简写),而这个变量,我们称之为指针变量。 换句话说,指针变量(一个标签)的值是指针,也就是内存地址。 根据变量指向的值,是否是内存地址,我把变量分为两种: - 普通变量:存数据值本身 - 指针变量:存值的内存地址 ## 1. 指针的创建 指针创建有三种方法 **第一种方法** 先定义对应的变量,再通过变量取得内存地址,创建指针 ```go // 定义普通变量 aint := 1 // 定义指针变量 ptr := &aint ``` **第二种方法** 先创建指针,分配好内存后,再给指针指向的内存地址写入对应的值。 ```go // 创建指针 astr := new(string) // 给指针赋值 *astr = "Go编程时光" ``` **第三种方法** 先声明一个指针变量,再从其他变量取得内存地址赋值给它 ```go aint := 1 var bint *int // 声明一个指针 bint = &aint // 初始化 ``` 上面的三段代码中,指针的操作都离不开这两个符号: - `&` :从一个普通变量中取得内存地址 - `*`:当`*`在赋值操作值的右边,是从一个指针变量中取得变量值,当`*`在赋值操作值的左边,是指该指针指向的变量 通过下面这段代码,你可以熟悉这两个符号的用法 ```go package main import "fmt" func main() { aint := 1 // 定义普通变量 ptr := &aint // 定义指针变量 fmt.Println("普通变量存储的是:", aint) fmt.Println("普通变量存储的是:", *ptr) fmt.Println("指针变量存储的是:", &aint) fmt.Println("指针变量存储的是:", ptr) } ``` 输出如下 ``` 普通变量存储的是: 1 普通变量存储的是: 1 指针变量存储的是: 0xc0000100a0 指针变量存储的是: 0xc0000100a0 ``` 要想打印指针指向的内存地址,方法有两种 ```go // 第一种 fmt.Printf("%p", ptr) // 第二种 fmt.Println(ptr) ``` ## 2. 指针的类型 我们知道字符串的类型是 string,整型是int,那么指针如何表示呢? 写段代码试验一下就知道了 ```go package main import "fmt" func main() { astr := "hello" aint := 1 abool := false arune := 'a' afloat := 1.2 fmt.Printf("astr 指针类型是:%T\n", &astr) fmt.Printf("aint 指针类型是:%T\n", &aint) fmt.Printf("abool 指针类型是:%T\n", &abool) fmt.Printf("arune 指针类型是:%T\n", &arune) fmt.Printf("afloat 指针类型是:%T\n", &afloat) } ``` 输出如下,可以发现用 `*`+所指向变量值的数据类型,就是对应的指针类型。 ``` astr 指针类型是:*string aint 指针类型是:*int abool 指针类型是:*bool arune 指针类型是:*int32 afloat 指针类型是:*float64 ``` 所以若我们定义一个只接收指针类型的参数的函数,可以这么写 ``` func mytest(ptr *int) { fmt.Println(*ptr) } ``` ## 3. 指针的零值 当指针声明后,没有进行初始化,其零值是 nil。 ```go func main() { a := 25 var b *int // 声明一个指针 if b == nil { fmt.Println(b) b = &a // 初始化:将a的内存地址给b fmt.Println(b) } } ``` 输出如下 ``` <nil> 0xc0000100a0 ``` ## 4. 指针与切片 切片与指针一样,都是引用类型。 如果我们想通过一个函数改变一个数组的值,有两种方法 1. 将这个数组的切片做为参数传给函数 2. 将这个数组的指针做为参数传给函数 尽管二者都可以实现我们的目的,但是按照 Go 语言的使用习惯,建议使用第一种方法,因为第一种方法,写出来的代码会更加简洁,易读。具体你可以参数下面两种方法的代码实现 **使用切片** ```go func modify(sls []int) { sls[0] = 90 } func main() { a := [3]int{89, 90, 91} modify(a[:]) fmt.Println(a) } ``` **使用指针** ```go func modify(arr *[3]int) { (*arr)[0] = 90 } func main() { a := [3]int{89, 90, 91} modify(&a) fmt.Println(a) } ``` --- ![](http://image.python-online.cn/20200321153457.png)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

801 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传