Golang复习

news2025/1/11 17:02:26

文章目录

      • golang的特点
      • golang数据类型
        • 基本数据类型(值类型)
        • 引用数据类型
      • make和new
        • make
        • new
      • 浅拷贝,深拷贝
        • 深拷贝:
        • 实现深拷贝的方式:
        • 浅拷贝:
        • 实现浅拷贝的方式
      • 接口
        • 接口是什么
      • 某种类型可以比较吗
      • channel
        • 数据结构
          • 环形队列:
          • 等待队列
        • channel读写过程
          • 创建channel
          • 向一个channel中写数据过程如下:
          • 从一个channel读数据过程如下:
          • 关闭channel会发生什么
        • channel缓冲区的特点
          • 同步与非同步:
          • nil:
          • panic:
      • 切片
        • 数据结构
        • Slice的扩容
          • append操作实现扩容的过程
      • map
      • 数据类型是否线程安全
      • GMP调度
      • 垃圾回收机制

golang的特点

Golang 针对并发进行了优化,并且在规模上运行良好

自动垃圾收集明显比 Java 或 Python 更有效,因为它与程序同时执行

golang数据类型

基本数据类型(值类型)

  • 布尔类型

  • 数字类型

    • 整型

      根据有符号分为:有符号、无符号类型;

      根据占据的空间分为:8,16,32,64;

    • 浮点型

      float32:32位浮点型数;float64:64位浮点型数;

      complex64:32位实数和虚数;complex128:64位实数和虚数;

    • 其他

      byte:类似于uint8,代表了 ASCII 码的一个字符

      rune:类似于int32,表示的是一个 Unicode字符

      uint:与uint大小一样

      uintptr:无符号整型,用于存放一个指针

  • 字符串类型

  • 数组类型

  • 结构体类型

引用数据类型

  • 指针类型

  • Channel类型

  • 切片类型

  • Map类型

  • 函数类型

  • 接口类型

make和new

他们都是分配内存空间的内置函数

make

  • make 用于创建切片、映射和通道(slice、map、channel)等引用类型的数据结构。

  • 它返回一个已初始化并且可以使用的引用类型变量,通常用于创建动态大小的数据结构。

new

  • new 主要用于创建值类型的变量,如结构体、整数、浮点数等,而不是引用类型。

  • new 用于创建并返回一个指向新分配的零值的指针。

浅拷贝,深拷贝

深拷贝:

拷贝的是数据本身,创造一个新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值

实现深拷贝的方式:

  • 值类型:对于 Go 中的基本数据类型(如整数、浮点数、字符串、结构体,数组等),赋值或传递参数时会进行深拷贝。这意味着创建一个新的值,而不是共享数据。

    a := 10
    b := a // 深拷贝
    
    arr1 := [3]int{1, 2, 3}
    arr2 := arr1 // 深拷贝
    
  • 使用copy赋值的数据是深拷贝

    slice1 := []int{1, 2, 3}
    slice2 := []int{0, 0, 0}
    copy(slice2, slice1)
    slice2[0] = 10
    fmt.Printf("slice1:%v\n", slice1)	//slice1:[1 2 3]
    fmt.Printf("slice2:%v\n", slice2)	//slice2:[10 2 3]
    

浅拷贝:

拷贝的是数据地址,只复制指向的对 象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化

实现浅拷贝的方式

  • 引用数据类型默认赋值操作就是浅拷贝:slice2 := slice1

    arr1 := []int{1, 2, 3}
    arr2 := arr1 // 浅拷贝
    arr2[0] = 100
    fmt.Printf("slice1:%v\n", arr1)	//slice1:[100 2 3]
    fmt.Printf("slice2:%v\n", arr2)	//slice2:[100 2 3]
    

接口

接口是什么

  1. interface 是方法声明的集合

  2. 任何类型的对象实现了在interface 中声明的全部方法,则表明该类型实现了该接口

  3. interface可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值

举实例,

某种类型可以比较吗

可以比较的数据结构

  1. 基本数据类型:整数(int、int8、int16、int32、int64)、浮点数(float32、float64)、复数(complex64、complex128)、布尔值(bool)、字符串(string)等基本类型都可以进行比较。
  2. 数组:数组是值类型,如果数组的元素类型是可比较的,则整个数组可以进行比较。例如,[3]int 和 [3]int 可以进行比较。
  3. 结构体:结构体是用户自定义的复合数据类型,如果结构体的字段都是可比较的,则结构体可以进行比较。
  4. 指针:指针类型可以进行比较,但比较的是指针的地址值。
  5. 接口:接口类型可以进行比较,但比较的是接口的动态类型和动态值。

不可以比较的数据结构

  1. 切片:切片是引用类型,不能直接进行比较。你可以比较切片是否为nil,但不能比较两个切片的内容是否相同。
  2. 映射:映射也是引用类型,不能直接进行比较。你可以比较映射是否为nil,但不能比较两个映射的内容是否相同。
  3. 函数:函数类型不能进行比较。
  4. 通道:通道类型不能进行比较。

channel

channel主要用于进程内各goroutine间的通信

数据结构

type hchan struct {
    qcount   uint           // 当前队列中剩余元素个数
    dataqsiz uint           // 环形队列长度,即可以存放的元素个数
    buf      unsafe.Pointer // 环形队列指针
    elemsize uint16         // 每个元素的大小
    closed   uint32         // 标识关闭状态
    elemtype *_type         // 元素类型
    sendx    uint           // 队列下标,指示元素写入时存放到队列中的位置
    recvx    uint           // 队列下标,指示元素从队列的该位置读出
    recvq    waitq          // 等待读消息的goroutine队列
    sendq    waitq          // 等待写消息的goroutine队列
    lock 	 mutex          // 互斥锁,chan不允许并发读写
}
环形队列:

环形队列作为其缓冲区,队列长度是创建channel时候指定的
在这里插入图片描述

等待队列

从channel读数据,如果channel缓冲区为空或者没有缓冲区,当前goroutine会被阻塞。
向channel写数据,如果channel缓冲区已满或者没有缓冲区,当前goroutine会被阻塞。

被阻塞的goroutine将会挂在channel的等待队列中:

  • 因读阻塞的goroutine会被向channel写入数据的goroutine唤醒;
  • 因写阻塞的goroutine会被从channel读数据的goroutine唤醒;

channel读写过程

创建channel

创建channel的过程实际上是初始化hchan结构。其中类型信息和缓冲区长度由make语句传入,buf的大小则与元素大小和缓冲区长度共同决定。

向一个channel中写数据过程如下:
  1. 如果等待接收队列recvq不为空,说明缓冲区中没有数据或者没有缓冲区,此时直接从recvq取出G,并把数据写入,最后把该G唤醒,结束发送过程;
  2. 如果缓冲区中有空余位置,将数据写入缓冲区,结束发送过程;
  3. 如果缓冲区中没有空余位置,将待发送数据写入G,将当前G加入sendq,进入睡眠,等待被读goroutine唤醒;
从一个channel读数据过程如下:
  1. 如果等待发送队列sendq不为空,且没有缓冲区,直接从sendq中取出G,把G中数据读出,最后把G唤醒,结束读取过程;
  2. 如果等待发送队列sendq不为空,此时说明缓冲区已满,从缓冲区中首部读出数据,把G中数据写入缓冲区尾部,把G唤醒,结束读取过程;
  3. 如果等待发送队列sendq为空,但缓冲区中有数据,则从缓冲区取出数据,结束读取过程;
  4. 如果等待发送队列sendq为空,并且缓冲区中没有数据,将当前goroutine加入recvq,进入睡眠,等待被写goroutine唤醒;
关闭channel会发生什么
  • 把recvq中的G全部唤醒,本该写入G的数据位置为nil。
  • 把sendq中的G全部唤醒,但这些G会panic。

特点:

  • 关闭通道后,已经在通道中的数据仍然可以被读取,直到通道中的数据全部被读取完毕。之后再次去读取,读取操作将不会阻塞,而是立即返回其元素类型的零值
  • 关闭通道后,向管道中写数据会发生panic

channel缓冲区的特点

同步与非同步:

无缓冲的 channel 是同步的,有缓冲的 channel 是非同步的,缓冲满时发送阻塞

channel无缓冲时,发送阻塞直到数据被接收,接收阻塞直到读到数据;
channel有缓冲时,当缓冲满时发送阻塞,当缓冲空时接收阻塞。

nil:

如果给一个nil的 channel 发送数据,会造成永远阻塞。
如果从一个nil的 channel 中接收数据,会造成永久阻塞。

panic:

关闭值为nil的channel
关闭已经被关闭的channel
向已经关闭的channel写数据

切片

数据结构

Slice依托数组实现,底层数组对用户屏蔽,在底层数组容量不足时可以实现自动重分配并生成新的Slice。

type slice struct {
    array unsafe.Pointer	//array指向底层数组
    len   int				//len代表切片长度
    cap   int				//cap是底层数据的长度
}

Slice的扩容

  • 使用append向Slice追加元素时,如果Slice空间不足,将会触发Slice扩容,扩容实际上是重新分配一块更大的内存,将原Slice数据拷贝进新Slice,然后返回新Slice,扩容后再将数据追加进去。
  • 扩容操作只关心容量,会把原Slice数据拷贝到新Slice,追加数据由append在扩容结束后完成
append操作实现扩容的过程
  1. 假如Slice容量够用,则将新元素追加进去,Slice.len++,返回原Slice
  2. 原Slice容量不够,则将Slice先扩容,扩容后得到新Slice
  3. 将新元素追加进新Slice,Slice.len++,返回新的Slice。

如果是一次追加一个元素,在容量小于1024之前是每次扩容一倍,如果是一次追加多个元素,在容量小于1024之前是一次扩容到大于切片长度的最小的偶数

a := make([]int, 0, 0)
a = append(a, 1, 1, 1, 1, 1)
fmt.Println(cap(a))

加一个元素之后之后的切片跟原来的一样吗

是否线程安全(否,关于底层结构)

map

的底层,冲突和扩容,为啥无序,线程不安全

数据类型是否线程安全

GMP调度

数量,调度过程:P维护调度(注意专业词汇)(了解G的生命周期)

垃圾回收机制

特点:与别的语言的不同之处

流程:整理好语言

垃圾回收:根据板门的发展过程(标记清除法,三色标记法,混合写屏障

defer先关闭

defer receiver painc执行顺序

错误处理:

可预测,不可预测,panic(执行过程,里面涉及到receive)

a))




加一个元素之后之后的切片跟原来的一样吗

是否线程安全(否,关于底层结构)



### map

的底层,冲突和扩容,为啥无序,线程不安全



### 数据类型是否线程安全



### GMP调度

数量,调度过程:P维护调度(注意专业词汇)(了解G的生命周期)



### 垃圾回收机制



特点:与别的语言的不同之处

流程:整理好语言

垃圾回收:根据板门的发展过程(标记清除法,三色标记法,混合写屏障

)







defer先关闭

defer receiver painc执行顺序



错误处理:

可预测,不可预测,panic(执行过程,里面涉及到receive)



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

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

相关文章

flutter 里面自定义appbar

众所周知,fluuter里面的appbar 包含title, leading,action, bottom 如果我想在appbar里面自定一些内容,他会默认继承appbar的高度,且位置也没法自定义,如下图 这个时候我该怎么办? 在appbar里面将下面的内…

【JVM】对象死亡判断

文章目录 简述引用计数算法可达性分析算法4种对象引用finalize()方法回收方法区 简述 在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”&#x…

(17)线程的实例认识:wait,waitany,waitall,及经典死锁问题

一、文件构成 1、界面:一个textbox,四个button。 2、程序:前面(15)的book类与data类 private void AppendLine(string s){txtInfo.AppendText(string.IsNullOrEmpty(txtInfo.Text) ? s : $"{Environment.NewLine}{s}");…

Redis 7 第八讲 集群模式(cluster)架构篇

集群架构 Redis 集群架构图 集群定义 Redis 集群是一个提供在多个Redis节点间共享数据的程序集;Redis集群可以支持多个master 应用场景 Redis集群支持多个master,每个master又可以挂载多个slave读写分离支持数据的高可用支持海量数据的读写存储操作集群自带Sentinel的故障…

看懂UML类图

UML 统一建模语言(Unified Modeling Language,UML)是一种为面向对象系统的产品进行说明、可视化和编制文档的一种标准语言,是非专利的第三代建模和规约语言。UML是面向对象设计的建模工具,独立于任何具体程序设计语言。 类的表示 首先看那个…

ROS2中如何从欧拉角转换成四元素

ROS1中使用from tf.transformations import quaternion_from_euler导入quaternion_from_euler()即可调用。而ROS2中默认没有安装,需要单独安装一下ros-galactic-tf-transformations(我使用的ROS2是galactic,根据版本名不同做相应修改即可): …

Python GUI入门——tkinter编辑框、复选框、下拉菜单和按钮文本框的使用

简介 接上一次的tkinter编写界面相关内容,丰富点常用控件的方法,学会了这些控件布局和相关方 法属性,能够满足日常小工具的制作需求了。 搭建的界面框架如下图所示,功能可以自己添加。 界面代码 # -*- coding: utf-8 -*- impor…

第五章 树于二叉树 七、树和森林的遍历(广度优先遍历、深度优先遍历)

1、树的遍历 树是一种递归定义的数据结构,所以我们可以使用递归实现遍历。 (1)先根遍历(最先访问根节点)(深度优先遍历) 1.使用孩子兄弟表示法将其转化为二叉树的形式。 2.使用先序遍历二叉树…

面试2:通用能力

15丨如何做好开场:给自我介绍加“特效 第一层,满足面试官对信息的期待 这是对自我介绍的基本要求,把个人信息、主要经历、经验和技能有条理地组织起来, 有逻辑地讲出来。需要找出多段经历的关联性和发展变化,形成连…

分布式事务之 Seata 的部署和集成

文章目录 一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务 二、Docker 中跑 Seata三、微服务集成seata1.引入依赖2.修改配置文件 四、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取nacos…

Linux下go环境安装、环境配置并执行第一个go程序

一、安装 1.Golang对Linux的内核版本要求 GO对Linux内核版本最低要求是 2.6.23,对应要求操作系统版本是: RHEL 6.0CentOS 6.0即,不支持 (RHEL 和 CentOS) 的 (4.x or 5.x)。2.下载golang的代码版本 Golang的官网下载地址:https:…

Presto 之Pipeline

一. 前言 我们知道在Presto中有个叫Pipeline的概念,Pipeline其实就是一条包含各个算子的流水线,如下所示。本文主要介绍在Presto中,Pipeline是如何划分的。 二. Pipeline 在Presto中,一个Stage中包括一个或者多个Pipeline&#xf…

JavaWeb项目基础配置

这里写目录标题 前言1.pom.xml2.webxml3.连接JDBC4.常用代码4.1获取时间4.2实现上传文件需要用到第三方库fileupload 常用快捷键常用操作Tomcat基础操作&#xff1a; 前言 本文主要讲述了 1.pom.xml <?xml version"1.0" encoding"UTF-8"?><pro…

9.2QTday4作业

1 闹钟 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QtDebug> #include <QLabel> //标签类 #include <QLineEdit> //行编辑器类 #include <QPushButton> //按钮类 #include <QTextEdit> //文本编辑器…

STM32定时器定时及其应用

STM32定时器定时及其应用 定时器概述☆定时器相关配置CubeMX工程配置及程序实现固件库程序设计及实现 定时器概述 1. 工作原理 使用精准的时基&#xff0c;通过硬件的方式&#xff0c;实现定时功能。定时器核心就是计数器 2. 定时器分类   基本定时器&#xff08;TIM6~TIM7…

SiameseNet实战中文文本匹配任务

引言 本文我们通过SiameseNet模型来完成中文文本匹配任务&#xff0c;其中包含了文本匹配任务一般套路&#xff0c;后续只需要修改实现的模型。 数据准备 数据准备包括 构建词表(Vocabulary)构建数据集(Dataset) 本次用的是LCQMC通用领域问题匹配数据集&#xff0c;它已经…

RK3568-android11-适配ov13850摄像头

硬件连接 主要分为两部分: mipi接口:传输摄像头数据 i2c接口:配置摄像头和对焦马达芯片寄存器相关驱动 |-- arch/arm64/boot/dts/rockchip DTS配置文件 |-- drivers/phy/rockchip/|-- phy-rockchip-mipi-rx.c mipi dphy 驱动 |-- drivers/media||-- platform/rockchip/isp1…

20230903-闹钟

app.cpp #include "app.h" #include "ui_app.h" int k1 true;APP::APP(QWidget *parent):QWidget(parent),ui(new Ui::APP) {ui->setupUi(this);this->resize(380,300);this->setStyleSheet("background-color:cyan;");//设置样式spe…

关于指针的一些练习(1)

1. int main() {int a[3][2] { (0,1),(2,3),(4,5) };int* p;p a[0];printf("%d", p[0]);return 0; } 解析&#xff1a;a是一个3行2列的二维数组&#xff0c;对他进行初始化时大括号里面是逗号表达式&#xff0c;根据逗号表达式可以得到a数组中元素为1&#xff0c…

知识图谱推理研究综述9.3

综述分类 根据样本量大小的不同&#xff0c;将知识图谱推理方法分为多样本推理、少样本推理和零与单样本推理 KG定义&#xff1a;&#xff08;Y&#xff09; 知识图谱是以图的形式表示真实世界的实体与关系之间关系的知识库。 具体来说知识图谱是通过将应用数学、图形学、信…