Go语言基础:数据类型

news2025/4/4 21:43:59

一、基础数据类型:Go语言的积木块

1.1 数字类型全家福

package main

import (
    "fmt"
)

func main() {
    // 有符号整数类型
    var a int    = 42                        // int 类型,自动选择32或64位
    var b int8   = 127                       // int8 类型,8位有符号整数
    var c int16  = 32767                     // int16 类型,16位有符号整数
    var d int32  = 2147483647                // int32 类型,32位有符号整数
    var e int64  = 9223372036854775807       // int64 类型,64位有符号整数

    // 无符号整数类型
    var f uint   = 42                        // uint 类型,自动选择32或64位
    var g uint8  = 255                       // uint8 类型,8位无符号整数
    var h uint16 = 65535                     // uint16 类型,16位无符号整数
    var i uint32 = 4294967295                // uint32 类型,32位无符号整数
    var j uint64 = 18446744073709551615      // uint64 类型,64位无符号整数

    // 浮点数类型
    var k float32 = 3.14                     // float32 类型,32位浮点数
    var l float64 = 3.141592653589793        // float64 类型,64位浮点数

    // 复数类型
    var m complex64  = 1 + 2i                // complex64 类型,实部和虚部都是 float32
    var n complex128 = 1 + 2i                // complex128 类型,实部和虚部都是 float64

    // 打印每个变量的类型
    fmt.Printf("%T %T %T %T %T\n", a, b, c, d, e)
    fmt.Printf("%T %T %T %T %T\n", f, g, h, i, j)
    fmt.Printf("%T %T\n", k, l)
    fmt.Printf("%T %T\n", m, n)
}

1.2 字符与布尔类型

var ch byte = 'A'      		// ASCII字符
var unicodeCh rune = '中' // Unicode字符
var flag bool = true

1.3 字符串的特别之处

Go语言的字符串是不可变的,也就是说,一旦创建后就无法修改其中的内容。如果需要修改字符串的内容,通常的做法是将字符串转换成一个可变的字节切片([]byte)或字符切片([]rune),对切片进行修改后再转换回字符串。

s := "hello"
b := []byte(s)   // 将字符串转换为字节切片
b[0] = 'H'       // 修改字节切片中的内容
s2 := string(b)  // 将修改后的字节切片转换回字符串
fmt.Println(s2)  // 输出: "Hello"

二、复合数据类型:构建复杂结构

2.1 数组:刻板的容器

特点

  • 长度固定
  • 值类型(赋值会复制整个数组)
  • 类型包含长度信息:[3]int ≠ [5]int
var arr1 [3]int             	// [0 0 0]
arr2 := [...]int{1,2,3}     	// 编译器推导长度
arr3 := [2][3]int{{1,2}, {3}} // 多维数组

痛点时刻:当我们需要动态大小时怎么办?

2.2 切片:灵活的舞者

关键特性

  • 底层引用数组
  • 自动扩容机制
  • 长度 vs 容量
slice1 := make([]int, 3, 5) // 长度3,容量5
slice2 := arr2[1:3]         // 基于数组创建
slice3 := []int{1,2,3}      // 直接初始化

// 动态操作
slice3 = append(slice3, 4)  // 自动扩容
copy(slice1, slice2)        // 复制元素

扩容条件

  • 当向切片中追加元素(使用append函数)时,如果切片的长度未超过容量,则直接在底层数组上进行追加。
  • 如果追加元素后长度超过容量,Go会创建一个新的底层数组,并将旧切片的数据复制到新数组中。

扩容策略(目的:平衡内存使用和性能,避免频繁的内存分配和数据拷贝)

  • 如果切片的当前容量小于1024,新的容量一般是原来的2倍。
  • 如果切片的当前容量大于等于1024,新的容量会增加为原来的1.25倍(具体倍数可能会根据实现细节有所不同)。

注意事项

  • 扩容会导致新的内存分配和数据拷贝,因此如果预先知道切片的最大容量,最好在创建切片时指定容量以减少扩容的开销。
  • 由于扩容会创建新的底层数组,因此在扩容后,旧的切片和新的切片将不再共享同一个底层数组。

2.3 映射:闪电查询专家

特点

  • 键的类型必须是可比较的,而值可以是任意类型。
  • Map是引用类型,赋值操作不会复制整个映射。
  • 内置函数 make 用于初始化 map,使用时需注意防止空指针异常。
  • map 本身并不是线程安全的。具体来说,如果多个 goroutine 同时对一个 map 进行读写操作而没有采取适当的同步措施,那么程序可能会出现竞态条件(race condition),这可能导致不可预测的行为或崩溃。
m1 := make(map[string]int)
m2 := map[string]int{
    "apple": 5,
    "pear":  3,
}

// 安全操作
if count, exists := m2["banana"]; exists {
    fmt.Println(count)
}

// 遍历(无序!)
for k, v := range m2 {
    fmt.Println(k, v)
}

2.4 结构体:自定义数据蓝图

type Person struct {
    Name string
    Age  int
    Contact struct {
        Phone string
        Email string
    }
}

p := Person{
    Name: "Alice",
    Age:  30,
}
p.Contact.Phone = "123-4567"

三、变量 vs 常量:变与不变的哲学

3.1 变量声明三剑客

特点

  • 作用域:变量的作用域由声明的位置决定,在函数内声明的变量属于局部作用域,全局声明的变量则属于包级作用域。
  • 生命周期:局部变量随函数调用结束而销毁,而全局变量则在整个程序运行期间一直存在。
  • 可变性:变量在程序运行过程中其值是可以被修改的。
// 标准式
var x int = 10

// 类型推导
var y = "hello"

// 短声明(这种方式语法简洁,只能在函数内部使用,非常适合局部变量的声明,但不适用于全局变量。)
z := 3.14

// 分组声明(不推荐)
var (
    a = 1
    b = true
)

3.2 常量的奥妙

常量的特点

  • 不可变性:常量一旦赋值便不能再被修改,适用于需要保持固定值的场景。
  • 作用域:与变量类似,常量也有作用域的概念,取决于它们的声明位置。
  • 编译期常量:常量的值在编译期间确定,因此在运行时具有更高的效率。
  • 无地址分配:常量没有在内存中占据一个特定的地址,因为它们的值是直接嵌入到使用它们的代码中的。
const PI = 3.1415
const (
    Red = iota   // 0
    Green        // 1
    Blue         // 2
)

// 编译期计算
const MatrixSize = 10 * 10

关键差异

特性变量常量
可修改
内存地址
类型推导支持必须显式
作用域相同相同

3.3 生命周期探秘

var globalVar = "永生" // 包生命周期

func demo() {
    localVar := "临时工" // 函数执行期间存在
    fmt.Println(localVar)
}

内存小剧场:当函数执行结束,"临时工"会被垃圾回收器请出场外~


四、互动与思考

在学习过程中,我鼓励大家不断思考并动手实践。以下是一些问题和讨论话题,希望你能参与进来:

  1. 数据类型选择:在你以往的开发经历中,有没有遇到过数据类型选择不当导致性能问题的情况?你认为如何在保证代码简洁的前提下选择合适的数据类型?
  2. 复合数据类型使用场景:你觉得在何种场景下数组更合适,何种场景下又应该优先选择切片或映射?分享你的思考和实际案例吧!
  3. 变量和常量的管理:在大型项目中,如何合理规划变量和常量的作用域和生命周期?这不仅关乎代码质量,也涉及到团队协作和维护成本。

欢迎大家在评论区留言讨论,我们一起分享心得,共同进步!

学习检查清单

✅ 能说出3种数字类型的区别
✅ 会正确使用切片扩容
✅ 能区分 var 与 := 的使用场景
✅ 知道常量为什么不能取地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2325522.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据处理专题(四)

目标 使用 Matplotlib 进行基本的数据可视化。‍ 学习内容 绘制折线图 绘制散点图 绘制柱状图‍ 代码示例 1. 导入必要的库 import matplotlib.pyplot as pltimport numpy as npimport pandas as pd 2. 创建示例数据集 # 创建示例数据集data { 月份: [1月, 2月, 3…

【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解

【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解 文章目录 【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解前言YOLOV1的模型结构YOLOV1模型的基本执行流程YOLOV1模型的网络参数YOLOV1模型的训练方式 YOLOV1的核心思想前向传播阶段网格单元(grid cell)…

云钥科技多通道工业相机解决方案设计

项目应用场景分析与需求挑战 1. 应用场景 ‌目标领域‌:工业自动化检测(如精密零件尺寸测量、表面缺陷检测)、3D立体视觉(如物体建模、位姿识别)、动态运动追踪(如高速生产线监控)等。 ‌核心…

从零到一:ESP32与豆包大模型的RTC连续对话实现指南

一、对话效果演示 ESP32与豆包大模型的RTC连续对话 二、ESP-ADF 介绍 乐鑫 ESP-ADF(Espressif Audio Development Framework)是乐鑫科技(Espressif Systems)专为 ESP32 系列芯片开发的一款音频开发框架。它旨在简化基于 ESP32 芯…

【深度学习与实战】2.3、线性回归模型与梯度下降法先导案例--最小二乘法(向量形式求解)

为了求解损失函数 对 的导数,并利用最小二乘法向量形式求解 的值‌ 这是‌线性回归‌的平方误差损失函数,目标是最小化预测值 与真实值 之间的差距。 ‌损失函数‌: 考虑多个样本的情况,损失函数为所有样本的平方误差之和&a…

【Django】教程-2-前端-目录结构介绍

【Django】教程-1-安装创建项目目录结构介绍 3. 前端文件配置 3.1 目录介绍 在app下创建static文件夹, 是根据setting中的配置来的 STATIC_URL ‘static/’ templates目录,编写HTML模板(含有模板语法,继承,{% static ‘xx’ …

详解list容器

1.list的介绍 list的底层结构是双向带头循环链表,允许随机的插入和删除,但其内存空间不是连续的。随机访问空间能力差,需要从头到尾遍历节点,不像vector一样高效支持 2.list的使用 构造函数 1.默认构造函数:创建一个…

leetcode_977. 有序数组的平方_java

977. 有序数组的平方https://leetcode.cn/problems/squares-of-a-sorted-array/ 1.题目 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 示例 1: 输入:nums [-4,-1…

网络探索之旅:网络原理(第二弹)

上篇文章,小编分享了应用层和传输层深入的一点的知识,那么接下来,这篇文章,继续分享网络层和数据链路层。 网络层 了解这个网络层,那么其实就是重点来了解下IP这个协议 对于这个协议呢,其实也是和前面的…

深入剖析 JVM:从组成原理到调优实践

深入剖析 JVM:从组成原理到调优实践 深入剖析 JVM:从组成原理到调优实践一、JVM 组成架构:运行 Java 程序的 “幕后引擎”1.1 内存结构:数据存储的 “分区管理”1.2 执行引擎:字节码的 “翻译官”1.3 本地方法接口&…

阿里云下一代可观测时序引擎-MetricStore 2.0

作者:徐昊(博澍) 背景 作为可观测场景使用频度最高的数据类型,Metrics 时序数据在可观测领域一直占有着重要地位,无论是从全局视角来观测系统整体状态,还是从大范围数据中定位某一个异常的位置&#xff0…

从入门到精通【 MySQL】 数据库约束与设计

文章目录 📕1. 数据库约束✏️1.1 NOT NULL 非空约束✏️1.2 DEFAULT 默认值约束✏️1.3 UNIQUE 唯一约束✏️1.4 PRIMARY KEY 主键约束✏️1.5 FOREIGN KEY 外键约束✏️1.6 CHECK 约束 📕2. 数据库设计✏️2.1 第一范式✏️2.2 第二范式✏️2.3 第三范…

Dubbo 通信流程 - 服务的调用

Dubbo 客户端的使用 在 Dubbo 应用中,往类成员注解 DubboReference,服务启动后便可以调用到远端: Component public class InvokeDemoFacade {AutowiredDubboReferenceprivate DemoFacade demoFacade;public String hello(String name){// …

【数据结构】哈夫曼树

哈夫曼树 在学习哈夫曼树之前,先了解以下几个概念: 一:**路径长度:**在一棵树中,从一个节点到另一个节点所经过的“边”的数量,被我们称为两个节点之间的路径长度。 二:**树的路径长度&#xf…

HCIP(TCP)(2)

1. TCP三次握手 SYN (同步序列编号) 报文: 客户端发送 SYN 报文,开始建立连接,并初始化序列号。 SYN-ACK (同步序列编号-确认) 报文: 服务器收到 SYN 报文后,回复 SYN-ACK 报文,确认连接请求,并初始化自己的序列号和确…

基于Web的交互式智能成绩管理系统设计

目录 摘要 绪论 一、应用背景 二、行业发展现状 三、程序开发的重要意义 四、结语 1 代码 2 数据初始化模块 3 界面布局模块 4 核心功能模块 5 可视化子系统 6 扩展功能模块 7 架构设计亮点 功能总结 一、核心数据管理 二、智能分析体系 三、可视化系统 四、扩…

k8s日志管理

k8s日志管理 k8s查看日志查看集群中不是完全运行状态的pod查看deployment日志查看service日志进入pod的容器内查看日志 管理k8s组件日志kubectl logs查看日志原理 管理k8s应用日志收集k8s日志思路收集标准输出收集容器中日志文件 k8s查看节点状态失败k8s部署prometheus监控 k8s…

element-plus中,Loading 加载组件的使用

一.基本使用 给一个组件&#xff0c;如&#xff1a;table表格&#xff0c;加上v-loading"true"即可。 举例&#xff1a;复制如下代码。 <template><el-table v-loading"loading" :data"tableData" style"width: 100%"><…

Mybatis_Plus中的常用注解

目录 1、TableName TableId TableId的type属性 TableField 1、TableName 经过以上的测试&#xff0c;在使用MyBatis-Plus实现基本的CRUD时&#xff0c;我们并没有指定要操作的表&#xff0c;只是在 Mapper接口继承BaseMapper时&#xff0c;设置了泛型User&#xff0c;而操…

高并发金融系统,“可观测-可追溯-可回滚“的闭环审计体系

一句话总结 在高并发金融系统中&#xff0c;审计方案设计需平衡"观测粒度"与"系统损耗"&#xff0c;通过双AOP实现非侵入式采集&#xff0c;三表机制保障操作原子性&#xff0c;最终形成"可观测-可追溯-可回滚"的闭环体系。 业务痛点与需求 在…