云海的博客
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)

云海

服务端研发
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)
  • 接口
  • 数组
  • slice
  • map
  • 反射
  • sync.Pool
  • net包笔记
  • net-rpc分析
  • 指针
  • 数组排序
  • Context
  • sync.map
  • 锁
  • recover
  • 泛型
  • 类型和类型指针分析
  • make和new区别
  • channel
  • sync.Once
  • protobuf
  • GoLand debug(1)
  • 从零实现RPC框架
  • 从零开始学Go Origin框架
  • MongoDB pkg源码-findone
  • Golang
云海
2021-07-20

类型和类型指针分析

# 概述

在定义函数和方法的时候,作为一名开发人员,一定会对函数的参数和返回值定义为T和*T深思熟虑,有些情况下可能还会有些苦恼。

一般的判断标准是看副本创建的成本和需求。

  • 1.不想变量被修改。如果你不想要变量被函数和方法修改,那么选择类型T。相反,如果想要修改原始的变量,则选择*T。
  • 2.如果变量是一个大的struct或者数组,则副本的创建相对会影响性能,这个时候考虑使用*T,只创建新的指针,这个区别还是巨大的
  • 3.(不针对函数参数,只针对本地变量) 对于函数作用域内的参数,如果定义为T,Go编译器尽量将对象分配到栈上,而*T很可能会分配到对象上,这对垃圾回收有影响。
# 什么时候发生副本创建
  • 变量赋值的时候就会创建对象副本。
  • slice、map和数组在初始化和按索引设置的时候也会创建副本。
  • for-range循环也是将元素赋值给循环变量,所以变量得到的是集合元素的副本。
  • 往channel中send对象的时候也会创建对象的副本
  • 将变量作为参数传递给函数和方法就会发生副本的创建。对于返回值,将返回值赋值给其它变量或者传递给其它的函数或方法,就会创建副本。
# 不同类型的副本创建
# bool,数值和指针

bool和数值类型一般不必考了指针类型,原因在于这些对象很小,创建副本的开销可以忽略。只有你在想修改同一个变量的值的时候才考虑他们的指针。

# 数组

数组是值类型,赋值的时候会发生原始数组的复制,所以对于大的数组的参数传递和赋值,一定要慎重。 对于[...]T和[...]*T的区别,[...]*T 创建的副本的元素是元数组元素指针的副本。

# map、slice和channel

这三种类型都是指向指针类型,指向一个底层的数据结构。因此,定义类型的时候,就不必定义成*T。

# 字符串

字符串比较特殊,它的值不能修改,任何想对字符串的值做修改都会生成新的字符串。 当你需要nil值的时候,就必须定义为*string。因为类型string的空值为“”。

# 函数

函数也是一个指针类型,对函数对象的赋值只是又创建了一个对次函数对象的指针。

上次更新: 2023/01/11
泛型
make和new区别

← 泛型 make和new区别→

最近更新
01
函数
04-11
02
面试题
04-11
03
EFK日志收集系统单机版
08-18
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式