Go语言学习
  • README
  • Go 基础
    • go语言介绍
    • go语言主要特性
    • go内置类型和函数
    • init函数和main函数
    • 下划线
    • iota
    • 字符串
    • 数据类型:数组与切片
    • 数据类型:byte、rune与字符串
    • 变量的5种创建方式
    • 数据类型:字典
    • 指针
    • 数据类型:指针
    • 类型断言
    • 流程控制:defer延迟执行
    • 异常机制:panic和recover
    • 函数
    • go依赖管理
    • go中值传递、引用传递、指针传递区别
  • 标准库
    • Go net/http包
  • 数据结构
    • 哈希表
      • 为什么对 map 的 key 或 value 进行取址操作是不允许的
  • Gin
    • gin 快速开始
    • gin-swagger用法
  • Go 进阶
    • Go 指针
    • Go 中的 GC 演变是怎样的?
    • Go 的堆和栈
  • 面向对象
    • make 和 new 的区别
    • new(T) 和 &T{} 有什么区别?
  • 并发编程
    • Channel
    • Go语言 CSP 并发模型
    • GMP 模型原理
      • GMP 模型为什么要有 P ?
    • Go 协程池(goroutine pool)
    • Go语言常见的并发模式
    • Go并发实践:主动停止goroutine
  • 最佳实践
    • 发布Go语言模块
  • 软件包
    • 常用的GoLang包工具
    • Go的UUID生成
    • 现代化的命令行框架Cobra
    • 配置解析神器Viper
    • Go发送邮件gomail
    • Go反射框架Fx
    • NSQ消息队列的使用
    • Go爬虫框架colly
    • grpc-go 的安装和使用
Powered by GitBook
On this page
  • 什么是指针
  • 指针的创建
  • 指针的零值
  • 指针与切片

Was this helpful?

  1. Go 基础

数据类型:指针

什么是指针

var name string = "Hello world"

当定义一个变量 name,name只是编程语言中方便程序员编写和理解代码的一个标签。 当我们访问这个标签[name]时,机算机会返回它指向的内存地址里存储的值:Hello world。 出于某些需要,我们会将这个内存地址赋值给另一个变量名,通常叫做 ptr(pointer的简写),而这个变量,我们称之为指针变量。 换句话说,指针变量指向了值的内存地址 根据变量指向的值,是否是内存地址,变量分为两种:

  • 普通变量:存数据值本身

  • 指针变量:存值的内存地址

指针的创建

第一种方法

先定义对应的变量,再通过变量取得内存地址,创建指针

// 定义普通变量
aint := 1
// 定义指针变量
ptr := &aint

第二种方法

先创建指针,分配好内存后,再给指针指向的内存地址写入对应的值。

// 创建指针
astr := new(string)
// 给指针赋值
*astr = "Hello world"

第三种方法

先声明一个指针变量,再从其他变量取得内存地址赋值给它

aint := 1
var bint *int  // 声明一个指针
bint = &aint   // 初始化

上面的三段代码中,指针的操作都离不开这两个符号:

  • &:从一个普通变量中取得内存地址

  • *:当*在赋值操作值的右边,是从一个指针变量中取得变量值,当*在赋值操作值的左边,是指该指针指向的变量

通过下面这段代码,你可以熟悉这两个符号的用法

package main

import "fmt"

func main() {
    aint := 1     // 定义普通变量
    ptr := &aint  // 定义指针变量
    fmt.Println("普通变量存储的是:", aint)
    fmt.Println("普通变量存储的是:", *ptr)
    fmt.Println("指针变量存储的是:", &aint)
    fmt.Println("指针变量存储的是:", ptr)
}

输出如下

普通变量存储的是: 1
普通变量存储的是: 1
指针变量存储的是: 0xc0000a0090
指针变量存储的是: 0xc0000a0090

要想打印指针指向的内存地址,方法有两种

// 第一种
fmt.Printf("%p", ptr)

// 第二种
fmt.Println(ptr)

指针的零值

当指针声明后,没有进行初始化,其零值是 nil。

func main() {
    a := 25
    var b *int  // 声明一个指针

    if b == nil {
        fmt.Println(b)
        b = &a  // 初始化:将a的内存地址给b
        fmt.Println(b)
    }
}

输出如下

<nil>
 0xc0000a0090

指针与切片

切片与指针一样,都是引用类型

如果我们想通过一个函数改变一个数组的值,有两种方法

  1. 将这个数组的切片做为参数传给函数

  2. 将这个数组的指针做为参数传给函数

尽管二者都可以实现我们的目的,但是按照 Go 语言的使用习惯,建议使用第一种方法,因为第一种方法,写出来的代码会更加简洁,易读。

具体可以参考下面两种方法的代码实现

使用切片

func modify(sls []int) {
    sls[0] = 90
}

func main() {
    a := [3]int{89, 90, 91}
    modify(a[:])
    fmt.Println(a)
}

使用指针

func modify(arr *[3]int) {
    (*arr)[0] = 90
}

func main() {
    a := [3]int{89, 90, 91}
    modify(&a)
    fmt.Println(a)
}o
Previous指针Next类型断言

Last updated 2 years ago

Was this helpful?