Go语言程序设计(十七)并发编程

学习Go语言,这23个网站给你整理好了 学习Go语言的教程网址 阅读详情

一、操作系统提供的并发基础

1、进程

        进程是在并发环境下,程序的一次动态执行过程。它由进程控制块(PCB)、程序和数据三部分组成,进程在它的生命周期内可能处于执行、就绪、阻塞三种基本状态。
        在多任务操作系统中,多个进程可以并发执行,而且进程是系统资源分配的基本单位。系统中每个进程都有自已的内存映像区,且互不影响,所以管理简单,但缺点是系统开销大。所以,系统能同时创建的进程数量是有限的,不能太多。


2、线程

        由于进程的系统开销大,操作系统的设计者又提出了更小的能独立运行的单位一一线程,试图用它来提高系统内程序并发执行的程度,从而进一步提高系统的吞吐量。
        在操作系统中,线程是由进程创建的,所以它继承了进程的部分资源,且具有进程的一些基本特征。所以多个线程之间也可以并发执行,且比进程的系统开销小。但是,和进程一样,线程依然是由系统内核管理的,所以在高并发模式下,系统能创建的线程数量依然有限,效率也并不高。


3、协程

        协程本质上是一种用户态线程,不需要操作系统进行抢占式调度,而且在真正的实现中寄存于线程中。因此,协程系统开销极小,可以有效提高线程任务的并发性,避免高并发模式下线程的缺点。协程的最大优势在于其“轻量级”,可以轻松创建上百万个而不会导致系统资源衰竭,而系统最多能创建的进程、线程的数量却少得多。
        使用协程的优点是编程简单,结构清晰。但缺点是需要语言的支持,如果语言不支持,则需要用户在程序中自行实现调度。目前,原生支持协程的语言还很少。

二、Goroutine

1、Goroutine的定义

        Go语言在语言级别支持轻量级线程,叫做Goroutine。Go语言标准库提供的所有系统调用操作(包括同步I/O操作),都会让出处理机给其他Goroutine。这使得轻量级线程的切换管理不依赖于系统的进程和线程,也不依赖于CPU的核心数量。
        Goroutine是Go语言运行库的功能,不是操作系统提供的功能,Goroutine不是用线程实现的。Goroutine 就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。因为节省了频繁创建和销毁线程的开销,所以它相对于进程、线程系统开销非常小,是轻量级的。可以很轻松地创建上百万个Goroutine,但它们并不是被操作系统所调度执行。

2、Goroutine的创建

        Goroutine是Go语言中的轻量级线程实现,由Go运行时管理(Runtime)。在一个函数调用前加上关键字“go",这次调用就会在一个新的Goroutine中并发执行。当被调用的函数返回时,这个Goroutine也就自动结束了。需要注意的是,如果这个函数有返回值,那么这个返回值会被丢弃。
        在Go语言中,可以使用关键字“go"创建并发执行的Goroutine。基本格式如下:

go func()

例如:

func test() {
    fmt. Println("Go...")
}

func main() {
    for i :=0; i< 10; i++{
        go test()
    }
}

        在上面的例子中,在一个for循环中一共调用了10次test()函数,它们是并发执行的。可是在编译执行上述代码时,会发现显示器没有任何输出信息,要解释这种现象,首先要了解Go语言程序的执行机制。
        Go程序从初始化main package并执行main()函数开始,当main()函数返回时程序退出,并且程序并不等待其他Goroutine结束。对于上述例子,main()函数启动了10个Goroutine,然后就直接返回退出了。而被启动的执行test()函数的10个Goroutine并没有来得及执行,所以程序没有任何输出结果。
        在多进程或多进程编程时,操作系统解决上述问题的方法是,让父进程等待线程执行结束后再退出,比如使用WaitForSingleObject之类的调用,来等待所有线程执行完毕。而Go语言有自已特有的解决方式,那就是Channel(通道)。Channel可以在Goroutine之间进行通信,这样main()函数就可以知道Goroutine何时退出。通过Channel,main()函数就可以等待所有Goroutine都退出了自己再退出。
        所以,在使用Go语言设计并发程序时,通常是Goroutine和Channel配合使用,二者不可缺其一。

三、Channel

1、程序间的并发通信

(1)共享内存
        共享内存是指多个并发单位分别保存对同一个数据的引用,实现对该数据的共享。被共享的数据可以有多种形式,比如内存数据块、磁盘文件、网络数据等,在实际应用中最常见的就是内存数据块。
        多个并发单位在同时访问共享内存时,必须使用互斥锁等相关机制,以保证对共享内存的互斥访问。这就造成了在多个并发单位间使用共享内存通信时,程序结构往往比较复杂,程序逻辑结构难于控制等问题。
(2)消息机制
        Go语言是以并发编程作为语言的最核心优势,所以在处理程序并发模型时,它不再采用共享内存作为并发单位之间的通信手段,而是以消息机制作为主要通信方法。
        消息机制规定每个并发单位是自包含的、独立的个体,并且都有自己的变量,这些变量不能在不同的并发单位之间共享。每个并发单位的输入、输出只有一种,那就是消息。这有点类似于进程的概念,每个进程都不会被其他进程打扰,它只做好自己的工作就行了。不同进程间靠消息进行通信,而不会共享内存数据。

2、Channel简介

        Go语言提供的消息通信机制被称为Channel,它类似于单双向数据管道(Pipe),用户可以使用Channel在两个或多个Goroutine之间传递消息。Channel从设计上确保同一时刻只有一个Goroutine能从中接收数据,这就避免了使用互斥锁的问题。另外,Channel中数据的发送和接收都是原语操作,不会中断,只会失败。
        Channel是进程内的通信方式,因此通过Channel传递对象的过程和调用函数时的参数传递行为比较一致,当然也可以传递指针等。如果需要跨进程进行通信,一般建议使用分布式系统的方法来解决,比如使用网络套接字(Socket)或者HTTP等通信协议。

3、Channel声明和初始化

        在Go语言中,Channel是引用类型,也是类型相关的,也就是说一个Channel只能传递一种类型的值,这个类型需要在声明Channel时指定。Channel的一般声明形式如下:

var chanName chan ElementType

        从上式可以看出,Channel的声明格式和一般变量声明基本相同,只是在类型前加了个关键字“chan”。ElementType指定Channel所能传递的元素类型。
例如:

var ch chan int

        该例中,ch是一个可以传递int类型的Channel。
Channel除了可以传递基本类型的数据,还可以作为Array、Slice或Map的元素。
例如:

var chs [10]chan int

该例中,chs是一个包含10个可传递int类型数据的Channel。
还可以使用make()函数直接声明并初始化Channel,

例如:

ch : = make( char int)

该例中声明并创建了ch,并为其分配了内存。

4、数据接收和发送

        Channel的主要用途是在不同的Goroutine之间传递数据,它使用通道运算符“<-”接收或者发送数据,将一个数据发送(写入)至Channel的语法如下:

ch <- value

        向Channel写入数据通常会导致程序阻塞(Block),直到有其他Goroutine从这个Channel中读取数据。从Channel中接收(读取)数据的语法如下:

value :=<- ch

        如果Channel之前没有写入数据,那么从Channel中读取数据也会导致阻塞,直到Channel中被写入数据为止。

5、Channel的关闭和迭代器

        关闭Channel非常简单,直接使用Go语言提供的内置丽数close()即可。关闭Channel的操作语句如下:

close( chanName)

        在关闭了一个Channel之后,往往用户还需判断Channel是否被关闭,这时可以在读取Channel的时候使用多重返回值的方式,例如:

value,ok :=<- ch

        这个用法与Map中按键值获取value的过程比较类似,只需要看第二个bool返回值即可。如果返回值是false则表示Channel已被关闭,否则主函数还要继续阻塞接收或者发送。
        对Channel的读取操作还可以使用range迭代器来完成,range操作直至Channel关闭(Close)方才终止循环。另外,在Go语言中,还经常把创建Goroutine和Channel的工作放在一个匿名函数中来完成。

        只有发送端(另一端正在等待接收)才能关闭Channel,只有接收端才能获得关闭状态。Close调用不是必需的,但如果接收端使用range或者循环接收数据,就必须调用Close,否则就会导致“throw: all goroutines are asleep-deadlock !”错误。

6、单向Channel

前面例子中列举的通道既能发送数据,也能接收数据,被称为双向通道(Duplexchannel)。还可以将Channel指定为单向通道(Simplex- channel),即只能接收,或只能发送。在将一个Channel变量传递到一个函数时,可以通过将其指定为单向Channel变量,从而限制该函数对此Channel的操作,比如只能从此Channel读,或只能往该Channel写。
只能接收的Channel变量定义形式如下:

var chanName chan <- ElementType

只能发送的Channel变量定义形式如下:

var chanName <- chan ElementType

        在定义了单向Channel后,还要对其初始化。在Go语言中,Channel是引用数据类型,也是一个原生数据类型,因此不仅支持被传递,还支持类型转换。所以,单向Channel可以由一个已定义的双向(正常)Channel转换而来。
例如:

ch := make(chan int)
chRead :=<- chan int(ch)
chWrite := chan <- int(ch)

        该例中基于ch,通过类型转换初始化了两个单向Channel:chRead是一个单向读Channel,chWrite是一个单向写Channel。

7、异步Channel

        前面的举例创建的都是不带Buffer的Channel,这种做法只适用于传递单个数据的应用场合,而对需要持续传输大量数据的应用场合就不适用了。对于在Goroutine间传输大量数据的应用,可以使用异步通道(Asynchronouschannel),从而达到消息队列的效果。

        异步Channel,就是给Channel设定一个Buffer值。在Buffer未写满的情况下,不阻塞发送操作;在Buffer未读完之前,不阻塞接收操作。这里的Buffer是指被缓冲的数据对象的数量,而不是内存大小。
要创建一个带Buffer的Channel,只需要在调用make()函数时,将缓冲区的大小作为第二个参数传入即可。
例如:

ch : = make(chan int, 1024)

        该例创建了一个大小为1024 的int类型Channel,即使没有读取方,写入方也可以一直往Channel中写入数据,在缓冲区被写满之前都不会阻塞。
        从带Buffer的Channel中读取数据,可以使用与常规非缓冲Channel完全一致的方法,但一般是使用range来实现更为简洁的循环读取。

四、Select机制

        在Go语言中,Select机制主要用于解决通道通信中的多路复用问题。因为通道的接收操作往往是阻塞式的,所以Select机制还经常和超时机制配合使用,将阻塞式的通信转换为非阻塞式,以提高系统通信效率。

如果有多个Channel需要监听,就可以使用Select机制,随机处理一个可用的Channel。Select的用法和Switch语句非常类似,由“select"开始一个新的选择块,每个选择条件由“case”语句来描述。与Switch语句可以使用任何形式条件表达式相比,Select机制有比较多的限制,其中最大的一条是每个“case”语句必须是一个I/O操作。

Select 机制的基本结构如下:

select {
    case <- chan1:
        //如果chan1成功读取数据,则进行该case处理语句.
    case <- chan2:
        //如果chan2成功读取数据,则进行该case处理语句.
        .
        .
        .
    default:
        //如果上面都没有成功,则进入default处理流程.
}

        可以看出,Select不像Switch语句,后面并不带判断条件,而是直接检测case语句。每个case语句都必须是一个面向Channel的操作。

Select机制的基本过程

(1)当所有被监听Channel中都无数据时,Select会一直等到其中一个有数据为止。
(2)当多个被监听Channel中都有数据时,Select会随机选择一个case执行。
(3)当所有被监听Channel中都无数据,且default子句存在时,则default子句会被执行。
(4)如果想持续监听多个Channel,需要使用for语句协助。
 

五、超时机制

        在前面所有举例中,所有对Channel操作的错误问题都被忽略了,没有进行错误处理的程序显然是不安全的。即在向Channel写数据时发现已满,或从Channel读数据时发现为空,如果不正确处理这些问题,很可能会导致整个Goroutine死锁。在Go语言并发编程的通信过程中,所有错误处理都由超时机制来完成。
        超时机制是一种解决通信死锁的机制,通常会设置一个超时参数,通信双方如果在设定的时间内仍然没处理完任务,则该处理过程会立即被终止,并返回对应的超时信息。
        Go语言没有提供直接的超时处理机制,但可以利用Select机制解决超时问题。因为Select的特点是只要其中一个case已经完成,程序就会继续往下执行,而不会考虑其他case的执行情况。基于此特性,就可以使用Select为Channel实现超时处理功能。

六、Runtime Goroutine

1、出让时间片

        在设计并发任务时,用户可以在每个Goroutine中控制何时主动让出时间片给其他Goroutine,这可以使用Gosched() 函数来实现。Gosched()类似于C#或Python中的Yield(函数迭代器),让出当前Goroutine的执行权限,调度器会安排其他等待的任务去运行,并在下轮某个时间片再从该位置恢复执行。

2、获取CPU核心数和任务数

        有时为了将多个并发执行的Goroutine分配给不同的CPU核心去完成,用户就需要知道CPU核心的具体数目。为此,runtime包提供了NumCPU()函数可以完成这个任务。
        为了观察系统任务调度情况,还可以使用NumGoroutine()函数返回正在执行和排队的任务总数。

3、终止当前Goroutine

        如果要强行终止一个Goroutine的执行,可以调用Goexit()函数来完成。Goexit()将终止整个堆栈链,并在内层退出,但是defer语句仍然或被执行。

golang基础教程(十七)GO并发原理_go高并发原理视频教程 每个P中的Goroutine不同导致他们运行的效率和时间也不同,在一个有很多P和M的环境中,不能让一个P跑完自身的Goroutine就没事可做了,因为或许其他的P有很长的goroutine队列要跑,得需要均衡。我们现在的计算机语言,可以狭义的认为是一种“软件”,它们中所谓的“线程”,往往是用户态的线程,和操作系统本身内核态的线程(简称KSE),还是有区别的。CSP并发模型是在1970年左右提出的概念,属于比较新的概念,不同于传统的多线程通过共享内存来通信,CSP讲究的是“以通信的方式来共享内存”。 阅读详情

相关推荐

无人机飞控技术最详细解读

已剪辑自: https://zhuanlan.zhihu.com/p/64519280[导读]被称作是“飞行器的大脑”的飞控到底是什么?以前,搞无人机的十个人有八个是航空、气动、机械出身,更多考虑的是如何让飞机稳定飞起来、飞得更快、飞得更高。如今,随着芯片、人工智能、大数据技术的发展,无人机开始了智能化、终端化、集群化的趋势,大批自动化、机械电子、信息工程、微电子的专业人材投入到了无人机研发大潮中,几年的时间让无人机从远离人们视野的军事应用飞入了寻常百姓家、让门外汉可以短暂的学习也能稳定可靠的飞行娱乐。不可

qq_41854911的博客 1万+

go并发编程

介绍之前,先澄清下并发这个概念,并发指的是多个任务被(一个)cpu 轮流切换执行,在 Go 语言里面主要用 goroutine (协程)来实现并发,类似于其他语言中的线程。

止语的博客 799

ST-LINK调试STM32H743必看:CubeMX工程中缺失的这行代码导致程序跑飞

本文深入剖析了使用ST-LINK调试STM32H743时,因CubeMX工程中缺失电源电压档位配置代码而导致程序跑飞或出现“Can not access memory”错误的问题。文章解释了H7系列电源与时钟耦合的核心原理,提供了具体的代码修复方案和系统化的调试排查思路,帮助开发者从根本上解决这一常见调试困境。

weixin_29191669的博客 281

Go 并发编程

关于 Go 语言之高性能并发编程的基础知识!

qq_46457076的博客 1580

差分分析.

差分分析是一种强大的密码攻击技术,通过研究明文差分与密文差分的关系来破解加密算法。本文系统介绍了差分分析的核心概念和方法: 基础差分分析:通过异或运算抵消密钥影响,利用差分分布表(DDT)寻找高概率差分特征,以FEAL-4为例展示了具体攻击过程。 高级差分技术:包括截断差分分析(关注部分特征)、不可能差分分析(排除概率为0的路径)和飞来去器分析(将算法分段处理)。 自动化搜索方法:介绍了松井算法和MILP(混合整数线性规划)方法,将差分路径搜索转化为数学优化问题。 这些方法展现了差分分析从基础理论到现代应用

weixin_61562383的博客 786

常见卫星图源下载教程

上面列出的8个常见的亚米级别数据源都可以通过xyz协议或者wmts/wms协议进行下载。这些协议是什么?地理信息数据为了方便网络传输,制定了一系列的地理数据传输标准(wms/wmts/xyz等)。协议特点优点缺点栅格数据支持矢量数据支持WMS通过HTTP请求获取GIS数据,服务器会将数据渲染成图像高度定制的地图;交互性强服务器渲染图像,响应时间较长支持有限支持WMTS提供预渲染的地图瓦片速度快,因为地图瓦片可以预先生成并在请求时快速提供瓦片的内容是预先确定的,无法进行定制支持。

锐多宝的地理空间 1万+

Go语言并发详解

文章目录一、Go语言并发简述(并发的优势)进程/线程并发/并行协程/线程Goroutine 介绍channel二、Go语言goroutine(轻量级线程)使用普通函数创建 goroutine1) 格式2) 例子使用匿名函数创建goroutine1) 使用匿名函数创建goroutine的格式2) 使用匿名函数创建goroutine的例子提示三、Go语言并发通信四、Go语言竞争状态简述Goroutine 7 (finished) created at: main.main() D:/code/src/m

qq_41854911的博客 1万+

8. Spring Ai之入门到精通(超级详细)

Spring AI 1.0.0 M1里程碑版本发布,标志着 Java 终于踏进Ai的时代半只脚。

gorgor在码农 3万+

GO并发编程

无缓冲channel:本质是一种同步通道,他要求读写操作紧密进行。所以,在单channel下,如果在无缓冲channel中进行读写,此时就会在第一次操作处阻塞,发生死锁。

2303_79380171的博客 1639

【毕设级教程】从0到1实现基于YOLOv8的UA-DETRAC交通目标检测系统(含UI界面,助力智能交通毕设)

本项目基于YOLOv8模型和UA-DETRAC数据集开发了一个交通目标检测系统,包含数据处理、模型训练和可视化界面全流程。UA-DETRAC数据集包含多种交通场景下的车辆标注,通过格式转换适配YOLOv8训练要求。系统采用PyQt开发交互界面,支持图像检测、结果显示等功能。该项目技术路线清晰,既展现深度学习在智能交通中的应用,又提供完整的可视化展示方案,适合作为计算机视觉相关毕业设计选题。

m0_64661770的博客 150

YOLOv11改进缝合注意力 | 深度优化的BiFormer模型-结合BiLevel Routing Attention与深度可分离卷积的创新应用(附代码)

YOLO(You Only Look Once)系列目标检测算法一直以来都是计算机视觉领域的热门选择。随着YOLOv11的发布,它在许多实际应用场景中取得了显著的性能提升。然而,面对日益复杂的目标检测任务,单纯依赖卷积神经网络(CNN)在某些情况下已经显得力不从心,特别是在处理小尺度、密集目标以及遮挡目标时,卷积操作的局部性限制了模型的表达能力。

一键难忘的博客 716

Go 语言编程基础:并发编程

Goroutine是 Go 中的轻量级线程,由 Go 运行时调度。Goroutines 可以通过go关键字来启动,并由 Go 运行时负责管理。Channel是 Goroutines 之间通信的机制,用于在不同的 Goroutines 之间传递数据。可以通过make函数创建 Channel,并指定数据传递的类型。示例ch := make(chan int) // 创建一个传递 int 类型的 Channel。

wushengT的博客 880

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【链块技术35期】区块链技术语言(二十七)——Go语言并发编程(上)

原文链接 区块链技术语言(二十七):Go语言并发编程(上) 并发编程分为上、下两节。这一节包括了并发编程的概述、goroutine和channel的部分内容。 一、概述 1.1 并行和并发 并行(parallel):在多个处理器上同时执行多条指令,如图1所示。 并发(concurrency):同一时刻只有一条指令在执行,但多个进程指令被快速轮换地执行,使得宏观上具有多个进程同时执行的...

链块学院 531

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

区块链技术语言(二十七)——Go语言并发编程(上)

并发编程分为上、下两节。这一节包括了并发编程的概述、goroutine和channel的部分内容。 一、概述 1.1 并行和并发并行(parallel):在多个处理器上同时执行多条指令,如图1所示。 并发(concurrency):同一时刻只有一条指令在执行,但多个进程指令被快速轮换地执行,使得宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的。它只是把这段时间进行划分、快速交替...

weixin_30301183的博客 126

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

4. Go 语言结构——《跟老吕学Go》

Go语言,又称Golang,是由Google开发的一种静态强类型、编译型的编程语言。Go语言旨在成为一门简洁、高效、可并发的编程语言,适用于构建大规模并发网络程序。下面将详细解释Go语言的主要结构。在Go语言中,函数是执行特定任务的代码块。// 函数体其中,是函数名,parameter1parameter2是函数的参数,type1type2是参数的类型,returnType是函数的返回类型,value是函数的返回值。在Go语言中,函数的定义使用func关键字,后面跟着函数名、参数列表和函数体。

Python老吕的博客 1356

golang基础教程(十七)GO并发原理

golang基础教程 一、GO并发原理 1、并发(CONCURRENCY)和并行(PARALLELLISM) 并发(CONCURRENCY):两个或两个以上的任务在一段时间内被执行。我们不必care这些任务在某一个时间点是否是同时执行,可能同时执行,也可能不是,我们只关心在一段时间内,哪怕是很短的时间(一秒或者两秒)是否执行解决了两个或两个以上任务。 并行(PARALLELLISM):两个或两个...

irich的博客 1万+

Golang超详细入门教程

Golang详细入门教程

席万里的博客 2966

【Golang 基础系列十七】Go语言反射

概述 在程序运行期对程序动态的进行访问和修改 reflect godoc:https://golang.org/pkg/reflect/ reflect包有两个数据类型: Type:数据类型 【reflect.TypeOf():是获取Type的方法】 Value:值的类型【reflect.ValueOf():是获取Value的方法】 语法 一、基本操作 获取变量类型 func Type...

郭枫的博客 588

Go语言开发(十七)、Go语言database/sql接口

Go语言开发(十七)、Go语言database/sql接口 一、database/sql接口 Go语言官方没有提供数据库驱动,而是为开发数据库驱动定义了标准接口database/sql,开发者可以根据database/sql接口来开发相应的数据库驱动,只要是按照标准接口database/sql开发的代码,以后需要迁移数据库时,不需要任何修改。 二、database/sql常用接口 1、sql.Re...

weixin_34127717的博客 623

通过示例学习 Go 语言 2023(十七)

恐慌类似于 golang 中的异常。恐慌是为了在异常条件下退出程序。程序中可能以两种方式发生恐慌。程序中的运行时错误通过显式调用 panic 函数。这可以由程序员在程序无法继续并必须退出时调用。Go 提供了一个特殊函数来创建恐慌。下面是该函数的语法。

龙哥盟 1209

40分钟学 Go 语言高并发教程目录

40分钟学 Go 语言高并发教程目录

weixin_40780178的博客 1364

Go最全golang基础教程(十七)GO并发原理_go高并发原理视频教程,大厂面经合集

并发(CONCURRENCY):两个或两个以上的任务在一段时间内被执行。我们不必care这些任务在某一个时间点是否是同时执行,可能同时执行,也可能不是,我们只关心在一段时间内,哪怕是很短的时间(一秒或者两秒)是否执行解决了两个或两个以上任务。并行(PARALLELLISM):两个或两个以上的任务在同一时刻被同时执行。并发说的是逻辑上的概念,而并行,强调的是物理运行状态。并发“包含”并行。

2401_84904900的博客 899

Go入门系列(十七) go并发之基于共享变量的并发

本系列文章目录 展开/收起 Go入门系列(一) 初识Go语言 Go入门系列(二) 变量、指针、数据类型简介和作用域 Go入门系列(三) 基础类型——整型、浮点型、布尔类型和字符串 Go入门系列(四) 数组Array和切片Slice Go入门系列(五) 哈希表map Go入门系列(六) 结构体s...

jqsfjqsf的博客 818

【Golang】Golang进阶系列教程--Go 语言 map 如何顺序读取?

Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。

DreamSun的博客 1174

Go语言学习笔记(十七)

命令行程序也叫命令行使用程序或工具,它被设计在终端运行。本章介绍如何使用Go语言创建命令行程序,您将了解如何分析参数以及如何创建子命令

LiMo-bit的杂货 485
上一篇: Go语言程序设计(十六)反射
下一篇: Effective Java(第三版)目录
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值