Go语言基础学习之指针详解

目录
  • 1. 什么是指针
  • 2. 指针地址 & 指针类型
  • 3. 指针取值
  • 4. 空指针
  • 5. make
  • 6. new
  • 7. make 和 new 的区别
  • 8. 问题

今天来说说 Go 语言基础中的指针。

Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。

1. 什么是指针

Go 语言中,一个指针变量指向了一个值的内存地址。和 C、C++ 中的指针不同,Go 语言中的指针不能进行计算和偏移操作。

Go 语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量。传递数据使用指针,而无须拷贝数据。

Go 语言中的指针操作非常简单,只有记住两个符号就可以了。

  • &(取地址)
  • *(根据地址取值)
var ip *int /* 指向整型*/

画个重点,我们想彻底搞明白指针,必须要掌握 3 个概念:

  • 指针地址
  • 指针类型
  • 指针取值

接下来我们从这 3 点大家阐述 Go 语言指针,方便大家掌握。

2. 指针地址 & 指针类型

Go 语言变量在运行时都会被指定一个内存地址,即变量在内存中的位置。Go 语言通常在使用时会在变量前放一个 & 代表对变量进行 “ 取地址 ” 操作。Go 语言常用的值类型 (string、int、array、struct、float、bool )都会有对应的指针类型。如:string、 int、*int64 等。

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。 Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如:int、int64、*string等。

取变量指针的语法如下:

package main

import "fmt"

func main(){

    a := 10   /* 声明实际变量 */
    ip := &a  /* 指针变量的存储地址 */

    fmt.Printf("a 变量的地址是: %x\n", &a  )

    /* 指针变量的存储地址 */
    fmt.Printf("ip 变量储存的指针地址: %x\n", ip )

    /* 使用指针访问值 */
    fmt.Printf("*ip 变量的值: %d\n", *ip )
}

运行结果:

a 变量的地址是: 0xc000010200

ip 变量储存的指针地址: 0xc000010200

*ip 变量的值: 10

其中:

  • a: 代表被取地址的变量,类型为 int
  • ip: 用于接收地址的变量,ip 的类型就为 *int,称做 int 的指针类型。*代表指针。

用图来表示一下 ip := &a:

以上就是指针地址和指针类型。

3. 指针取值

对变量使用 &会获取该变量的指针,对指针使用 * 会获取到值,也就是 “指正取值”。举个例子更好的理解一下:

package main

import "fmt"

func main() {

    a := 20   /* 声明实际变量 */
    b := &a  /* 指针变量的存储地址 */
    fmt.Printf("type of b:%T\n", &a  )

    c := *b // 指针取值(根据指针去内存取值)
    fmt.Printf("type of c:%T\n", c)
    fmt.Printf("value of c:%v\n", c)
}

控制台输出结果:

type of b:*int
type of c:int
value of c:10

小结一下:

  • 指针变量的值是指针地址 (可以结合上图更好的理解)
  • 对变量进行取地址 &操作,可以获得这个变量的指针变量
  • 对指针变量进行取值 *操作,可以获得指针变量指向的原变量的值

函数传值:

package main

import "fmt"

func main() {

    x := 2
    mod1(x)
    fmt.Println(x) // 2

    mod2(&x)
    fmt.Println(x) // 1024
}

func mod1(x int) {
    x = 1024
}

func mod2(x *int) {
    *x = 1024
}

4. 空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil

nil 指针也称为空指针。

nil在概念上和其它语言的 null、None、nil、NULL一样,都指代零值或空值。

一个指针变量通常缩写为 ptr

举个例子:

package main

import "fmt"

func main() {
   var  ptr *int
   fmt.Printf("ptr 的值为 : %x\n", ptr) // ptr 的值为 : 0
}

空指针判断:

package main

import "fmt"

func main() {
    var ptr *string
    fmt.Println(ptr)
    fmt.Printf("ptr的值是%v\n", ptr)

    if ptr != nil {
        fmt.Println("非空")
    }
    if ptr == nil {
        fmt.Println("空值")
    }
}

5. make

make 是用于初始化内置的数据结构,比如 slicemap 和 channel

func make(t Type, size ...IntegerType) Type

举个例子:

package main

import "fmt"

func main() {
    var user map[string]int
    user = make(map[string]int, 10)
    user["age"] = 18
    fmt.Println(user)

    /**
        slice := make([]int, 0, 100)
        hash := make(map[int]bool, 10)
        ch := make(chan int, 5)
    **/
}

6. new

new 的作用是根据传入的类型分配一片内存空间并返回指向这片内存空间的指针。

func new(Type) *Type

解释一下:

  • Type 表示类型,new 函数只接受一个参数,这个参数是一个类型
  • *Type 表示类型指针,new 函数返回一个指向该类型内存地址的指针

举个例子:

package main

import "fmt"

func main() {
    a := new(int)
    b := new(bool)
    fmt.Printf("%T\n", a) // *int
    fmt.Printf("%T\n", b) // *bool
    fmt.Println(*a)       // 0
    fmt.Println(*b)       // false
}

7. make 和 new 的区别

面试高频题,这个要考,记一下。

  • make 和 new 都是用来做内存分配
  • make 只用于 slice、map 、channel 的初始化,返回的还是这三个引用类型本身,因为这三种类型就是引用类型,所以就没必要返回其指针了
  • new 用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

8. 问题

Q: 执行下面的代码会出现啥问题?

package main

import "fmt"

func main() {
    var a *int
    *a = 100
    fmt.Println(*a)

    var user map[string]int
    user["age"] = 18
    fmt.Println(user)
}

A: 会出现 panic runtime error: invalid memory address or nil pointer dereference。出错行数在第 7 行。

原因:在 Go 语言中我们使用引用类型的变量需要先申明、分配内存空间,否则在赋值是会出错。值类型的变量除外,因为其在申明时就分配了默认的内存空间。这也是 new 和 make 的作用。

到此这篇关于Go语言基础学习之指针详解的文章就介绍到这了,更多相关Go语言指针内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Go语言学习教程之指针的示例详解

    目录 前言 练习1 练习2 练习3 前言 关于指针的主要几点: 指针类型:一个指针类型*T表示指向给定类型的变量的所有指针的集合,该给定类型T称为基本类型.未初始化的指针的值是nil. 变量:一个变量是保存一个值的存储位置.允许的值的集合由变量的类型决定. 寻址操作:对于类型为T的操作数x,寻址操作&x会产生一个指向x的类型为*T的指针.对于指针类型为*T的操作数y,指针间接寻址*y表示y指向的类型为T的变量. 本文使用的Go版本: $ go version go version go1.18

  • Go语言学习之指针的用法详解

    目录 引言 一.定义结构体 1. 语法格式 2. 示例 二.访问结构体成员 三.结构体作为函数参数 四.结构体指针 总结 引言 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合 结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性: Title :标题 Author : 作者 Subject:学科 ID:书籍ID 一.定义结构体 1. 语法格式 结构体定义需要使用 type 和 struc

  • 深入了解Golang的指针用法

    目录 1.指针类型的变量 2.Go只有值传递,没有引用传递 3.for range与指针 4.闭包与指针 5.指针与内存逃逸 与C语言一样,Go语言中同样有指针,通过指针,我们可以只传递变量的内存地址,而不是传递整个变量,这在一定程度上可以节省内存的占用,但凡事有利有弊,Go指针在使用也有一些注意点,稍不留神就会踩坑,下面就让我们一起来细嗦下. 1.指针类型的变量 在Golang中,我们可以通过**取地址符号&**得到变量的地址,而这个新的变量就是一个指针类型的变量,指针变量与普通变量的区别在于

  • Go语言指针用法详解

    结合这个例子分析一下 结果: 结合以往C语言的基础,画了一张图来解释为什么会有上面这些值的出现.先查看下Go中的这两个运算符是啥吧. ①对于所有带a的结果 var a int = 1 定义了一个变量a值为1,如下图所示: &a就是这个存放a变量值的地址 *&a 就是指向&a的一个指针,*&a = a = 1 ②所有带b结果 var b *int = &a 类似C语言的 int *b = &a 定一个指向整形变量的指针b,b指向了a的地址 所以: b = &a

  • Go 语言的指针的学习笔记

    Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, func . 相比 Java,Python,Javascript 等引用类型的语言,Golang 拥有类似C语言的指针这个相对古老的特性.但不同于 C 语言,Golang 的指针是单独的类型,而不是 C 语言中的 int 类型,而且也不能对指针做整数运算.从这一点看,Golang 的指针基本就是一种引用

  • Go语言基础学习之指针详解

    目录 1. 什么是指针 2. 指针地址 & 指针类型 3. 指针取值 4. 空指针 5. make 6. new 7. make 和 new 的区别 8. 问题 今天来说说 Go 语言基础中的指针. Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务. 1. 什么是指针 Go 语言中,一个指针变量指向了一个值的内存地址.和 C.C++ 中的指针不同,Go 语言中的指针不能进行计算和偏移操作. Go 语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一

  • C语言算法学习之双向链表详解

    目录 一.练习题目 二.算法思路 1.设计浏览器历史记录 2.扁平化多级双向链表 3.展平多级双向链表 4.二叉搜索树与双向链表 一.练习题目 题目链接 难度 1472. 设计浏览器历史记录 ★★★☆☆ 430. 扁平化多级双向链表 ★★★☆☆ 剑指 Offer II 028. 展平多级双向链表 ★★★☆☆ 剑指 Offer 36. 二叉搜索树与双向链表 ★★★★☆ 二.算法思路 1.设计浏览器历史记录 1.这是一个模拟题: 2.初始化生成一个头结点,记录一个当前结点: 3.向前 和 向后 是两

  • Java基础学习之接口详解

    目录 概述 定义格式 含有抽象方法 含有默认方法和静态方法 含有私有方法和私有静态方法 基本的实现 实现的概述 抽象方法的使用 默认方法的使用 静态方法的使用 私有方法的使用 接口的多实现 抽象方法 默认方法 静态方法 优先级的问题 接口的多继承 其他成员特点 概述 接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量.构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法 (JDK 9). 接

  • Go语言基础模板设计模式示例详解

    目录 概述 模板模式生活案例 策略模式涉及到两个角色 UML 总结 示例 概述 模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式.让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤 确定了步骤的执行顺序,单某些步骤因环境或人等因素具体实现是未知的 模板模式生活案例 请客吃饭[点菜->吃东西->结账],每个人点菜不一样,吃东西不一样,结账也不一样从某地到某地[起点->出行方式->终点]起点和终点不一一样,但是每个人出行方式是不一样的 Go没有封装.

  • Java基础学习之构造方法详解

    目录 一.构造方法概述 二.构造方法的注意事项 三.标准类制作 一.构造方法概述 构造方法是一种特殊的方法 作用:创建对象Student stu = new Student(); 格式: pucli class 类名{        修饰符 类名(参数){        } } 功能:主要是完成对象数据的初始化 示例代码: class Student { private String name; private int age; //构造方法 public Student() { System.

  • C语言 结构体和指针详解及简单示例

    指针也可以指向一个结构体,定义的形式一般为: struct 结构体名 *变量名; 下面是一个定义结构体指针的实例: struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 float score; //成绩 } stu1 = { "Tom", 12, 18, 'A', 136.5 }; //结构体指针struct stu *pstu = &stu1; 也可以在定义结构体的同时定义结构

  • Go语言基础学习之数组的使用详解

    目录 1. Array(数组) 2. 声明数组 3. 数组初始化 3.1 方式一 3.2 方式二 3.3 方式三 3.4 多维数组 4. 遍历数组&取值 5. 数组拷贝和传参 数组相必大家都很熟悉,各大语言也都有数组的身影.Go 语言也提供了数组类型的数据结构. 1. Array(数组) 数组是同一种数据类型的固定长度的元素集合.在 Go 语言中,数组声明后长度就不能改变了,可以修改数组的元素,用法: // eg: 定义一个长度为 10 的 int 数组 var a [10]int 2. 声明数

  • C语言指针详解及用法示例

    新手在C语言的学习过程中遇到的最头疼的知识点应该就是指针了,指针在C语言中有非常大的用处.下面我就带着问题来写下我对于指针的一些理解. 指针是什么? 指针本身是一个变量,它存储的是数据在内存中的地址而不是数据本身的值.它的定义如下: int a=10,*p; p=&a int a=10; int *p=&a; 首先我们可以理解 int* 这个是要定义一个指针p,然后因为这个指针存储的是地址所以要对a取地址(&)将值赋给指针p,也就是说这个指针p指向a. 很多新手都会对这两种定义方法

  • Go语言学习之goroutine详解

    什么是goroutine? Goroutine是建立在线程之上的轻量级的抽象.它允许我们以非常低的代价在同一个地址空间中并行地执行多个函数或者方法.相比于线程,它的创建和销毁的代价要小很多,并且它的调度是独立于线程的.在golang中创建一个goroutine非常简单,使用"go"关键字即可: package mainimport ( "fmt" "time")func learning() { fmt.Println("My firs

  • C语言指针详解

    前言:复杂类型说明     要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其优先级和运算优先级一样,所以我总结了一下其原则:从变量名处起,根据运算符优先级结合,一步一步分析.下面让我们先从简单的类型开始慢慢分析吧: int p; //这是一个普通的整型变量   int *p; //首先从P 处开始,先与*结合,所以说明P 是一个指针,然后再与int 结合,说明指针所

随机推荐