- 博客(345)
- 收藏
- 关注
转载 golang高并发模型
github上看到的一篇关于golang高并发性的文章,觉得写的非常好github 地址https://github.com/rubyhan1314/Golang-100-Days一、并发性Concurrency1.1 多任务#怎么来理解多任务呢?其实就是指我们的操作系统可以同时执行多个任务。举个例子,你一边听音乐,一边刷微博,一边聊QQ,一边用Markdown写作业,这就是多任务,至少同时有4个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是界面上没有显示而已。1.2 什么是并.
2021-09-09 22:15:53
510
转载 Go语言CSP:通信顺序进程简述
Go实现了两种并发形式,第一种是大家普遍认知的多线程共享内存,其实就是Java或C++等语言中的多线程开发;另外一种是Go语言特有的,也是Go语言推荐的 CSP(communicating sequential processes)并发模型。CSP 并发模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享 channel(管道)进行通信的并发模型。Go语言就是借用 CSP 并发模型的一些概念为之实现并发的,但是Go语言并没有完全实现了 CSP 并发模型的所有理论,仅仅是实现了 proce
2021-09-06 22:17:20
442
转载 Go语言封装qsort快速排序函数
快速排序(Quick Sort)是由“东尼·霍尔”所设计的一种排序算法。在平均状况下,排序 n 个项目要Ο(n log n)次比较,在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n)算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性。qsort 快速排序函数是C语言中的一个高阶函数,支持用于自定义排序比较函数,可以对任意类型的数
2021-09-06 22:16:40
527
转载 Go语言死锁、活锁和饥饿概述
本节我们来介绍一下死锁、活锁和饥饿这三个概念。死锁死锁是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。死锁发生的条件有如下几种:1) 互斥条件线程对资源的访问是排他性的,如果一个线程对占用了某资源,那么其他线程必须处于等待状态,直到该资源被释放。2) 请求和保持条件线程 T1 至少已经保持了一个资源 R1 占用,但又提出使用另一个
2021-09-06 22:15:53
337
转载 Go语言等待组(sync.WaitGroup)
Go语言中除了可以使用通道(channel)和互斥锁进行两个并发程序间的同步外,还可以使用等待组进行多个任务的同步,等待组可以保证在并发环境中完成指定数量的任务在 sync.WaitGroup(等待组)类型中,每个 sync.WaitGroup 值在内部维护着一个计数,此计数的初始默认值为零。等待组有下面几个方法可用,如下表所示。等待组的方法方法名功能(wg * WaitGroup) Add(delta int)等待组的计数器 +1(wg * WaitGroup) Done()等待组的计数器 -
2021-09-06 22:14:56
247
转载 Go语言互斥锁(sync.Mutex)和读写互斥锁(sync.RWMutex)
Go语言包中的 sync 包提供了两种锁类型:sync.Mutex 和 sync.RWMutex。Mutex 是最简单的一种锁类型,同时也比较暴力,当一个 goroutine 获得了 Mutex 后,其他 goroutine 就只能乖乖等到这个 goroutine 释放该 Mutex。RWMutex 相对友好些,是经典的单写多读模型。在读锁占用的情况下,会阻止写,但不阻止读,也就是多个 goroutine 可同时获取读锁(调用 RLock() 方法;而写锁(调用 Lock() 方法)会阻止任何其他
2021-09-06 22:14:04
250
转载 Go语言竞态检测——检测代码在并发环境下可能出现的问题
Go语言程序可以使用通道进行多个 goroutine 间的数据交换,但这仅仅是数据同步中的一种方法。通道内部的实现依然使用了各种锁,因此优雅代码的代价是性能。在某些轻量级的场合,原子访问(atomic包)、互斥锁(sync.Mutex)以及等待组(sync.WaitGroup)能最大程度满足需求。本节只讲解原子访问,互斥锁和等待组将在接下来的两节中讲解。当多线程并发运行的程序竞争访问和修改同一块资源时,会发生竞态问题。下面的代码中有一个 ID 生成器,每次调用生成器将会生成一个不会重复的顺序序号
2021-09-06 22:12:57
411
转载 Go语言Telnet回音服务器——TCP服务器的基本结构
Telnet 协议是 TCP/IP 协议族中的一种。它允许用户(Telnet 客户端)通过一个协商过程与一个远程设备进行通信。本例将使用一部分 Telnet 协议与服务器进行通信。服务器的网络库为了完整展示自己的代码实现了完整的收发过程,一般比较倾向于使用发送任意封包返回原数据的逻辑。这个过程类似于对着大山高喊,大山把你的声音原样返回的过程。也就是回音(Echo)。本节使用 Go语言中的 Socket、goroutine 和通道编写一个简单的 Telnet 协议的回音服务器。回音服务器的代码分为 4
2021-09-06 22:12:14
667
转载 Go语言多核并行化
Go语言具有支持高并发的特性,可以很方便地实现多线程运算,充分利用多核心 cpu 的性能。众所周知服务器的处理器大都是单核频率较低而核心数较多,对于支持高并发的程序语言,可以充分利用服务器的多核优势,从而降低单核压力,减少性能浪费。Go语言实现多核多线程并发运行是非常方便的,下面举个例子:package mainimport ( "fmt")func main() { for i := 0; i < 5; i++ { go AsyncFunc(i) }}f
2021-09-06 22:10:52
434
转载 Go语言关闭通道后继续使用通道
通道是一个引用对象,和 map 类似。map 在没有任何外部引用时,Go语言程序在运行时(runtime)会自动对内存进行垃圾回收(Garbage Collection, GC)。类似的,通道也可以被垃圾回收,但是通道也可以被主动关闭。格式使用 close() 来关闭一个通道:close(ch)关闭的通道依然可以被访问,访问被关闭的通道将会发生一些问题。给被关闭通道发送数据将会触发 panic被关闭的通道不会被置为 nil。如果尝试对已经关闭的通道进行发送,将会触发宕机,代码如下:
2021-09-06 22:09:57
539
转载 Go语言使用通道响应计时器的事件
Go语言中的 time 包提供了计时器的封装。由于 Go语言中的通道和 goroutine 的设计,定时任务可以在 goroutine 中通过同步的方式完成,也可以通过在 goroutine 中异步回调完成。这里将分两种用法进行例子展示。一段时间之后(time.After)延迟回调:package main import ( "fmt" "time" ) func main() { // 声明一个退出用的通道 exit := make(chan int) //
2021-09-06 22:04:47
278
转载 Go语言RPC(模拟远程过程调用)
服务器开发中会使用RPC(Remote Procedure Call,远程过程调用)简化进程间通信的过程。RPC 能有效地封装通信过程,让远程的数据收发通信过程看起来就像本地的函数调用一样。本例中,使用通道代替 Socket 实现 RPC 的过程。客户端与服务器运行在同一个进程,服务器和客户端在两个 goroutine 中运行。我们先给出完整代码,然后再详细分析每一个部分。package main import ( "errors" "fmt" "time" ) // 模
2021-09-06 22:03:13
249
转载 Go语言通道的多路复用——同时处理接收和发送多个通道的数据
多路复用是通信和网络中的一个专业术语。多路复用通常表示在一个信道上传输多路信号或数据流的过程和技术。提示报话机同一时刻只能有一边进行收或者发的单边通信,报话机需要遵守的通信流程如下:说话方在完成时需要补上一句“完毕”,随后放开通话按钮,从发送切换到接收状态,收听对方说话。 收听方在听到对方说“完毕”时,按下通话按钮,从接收切换到发送状态,开始说话。电话可以在说话的同时听到对方说话,所以电话是一种多路复用的设备,一条通信线路上可以同时接收或者发送数据。同样的,网线、光纤也都是基于多路复用..
2021-09-06 22:01:28
1565
转载 Go语言channel超时机制
Go语言没有提供直接的超时处理机制,所谓超时可以理解为当我们上网浏览一些网站时,如果一段时间之后不作操作,就需要重新登录。那么我们应该如何实现这一功能呢,这时就可以使用 select 来设置超时。虽然 select 机制不是专门为超时而设计的,却能很方便的解决超时问题,因为 select 的特点是只要其中有一个 case 已经完成,程序就会继续往下执行,而不会考虑其他 case 的情况。超时机制本身虽然也会带来一些问题,比如在运行比较快的机器或者高速的网络上运行正常的程序,到了慢速的机器或者网络上运行
2021-09-05 21:48:17
185
转载 Go语言带缓冲的通道
Go语言中有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求 goroutine 之间必须同时完成发送和接收。通道会阻塞发送和接收动作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。这导致有缓冲的通道和无缓冲的通道之间的一个很大的不同:无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换;有缓冲的通道没有这种保证。在无缓冲通道的基础上,
2021-09-05 21:44:45
224
转载 Go语言无缓冲的通道
Go语言中无缓冲的通道(unbuffered channel)是指在接收前没有能力保存任何值的通道。这种类型的通道要求发送 goroutine 和接收 goroutine 同时准备好,才能完成发送和接收操作。如果两个 goroutine 没有同时准备好,通道会导致先执行发送或接收操作的 goroutine 阻塞等待。这种对通道进行发送和接收的交互行为本身就是同步的。其中任意一个操作都无法离开另一个操作单独存在。阻塞指的是由于某种原因数据没有到达,当前协程(线程)持续处于等待状态,直到条件满足才解除阻塞。
2021-09-05 21:42:38
176
转载 Go语言单向通道——通道中的单行道
Go语言的类型系统提供了单方向的 channel 类型,顾名思义,单向 channel 就是只能用于写入或者只能用于读取数据。当然 channel 本身必然是同时支持读写的,否则根本没法用。假如一个 channel 真的只能读取数据,那么它肯定只会是空的,因为你没机会往里面写数据。同理,如果一个 channel 只允许写入数据,即使写进去了,也没有丝毫意义,因为没有办法读取到里面的数据。所谓的单向 channel 概念,其实只是对 channel 的一种使用限制。单向通道的声明格式我们在将一个..
2021-09-05 21:37:06
218
转载 Go语言通道(chan)——goroutine之间通信的管道
如果说 goroutine 是 Go语言程序的并发体的话,那么 channels 就是它们之间的通信机制。一个 channels 是一个通信机制,它可以让一个 goroutine 通过它给另一个 goroutine 发送值信息。每个 channel 都有一个特殊的类型,也就是 channels 可发送数据的类型。一个可以发送 int 类型数据的 channel 一般写为 chan int。Go语言提倡使用通信的方法代替共享内存,当一个资源需要在 goroutine 之间共享时,通道在 goroutin..
2021-09-05 21:32:43
264
转载 goroutine和coroutine的区别
C#、Lua、Python语言都支持 coroutine 特性。coroutine 与 goroutine 在名字上类似,都可以将函数或者语句在独立的环境中运行,但是它们之间有两点不同:goroutine 可能发生并行执行; 但 coroutine 始终顺序执行。goroutines 意味着并行(或者可以以并行的方式部署),coroutines 一般来说不是这样的,goroutines 通过通道来通信;coroutines 通过让出和恢复操作来通信,goroutines 比 coroutines.
2021-09-05 21:28:30
280
转载 GO 并发和并行的区别
在讲解并发概念时,总会涉及另外一个概念并行。下面让我们来了解并发和并行之间的区别。并发(concurrency):把任务在不同的时间点交给处理器进行处理。在同一时间点,任务并不会同时运行。 并行(parallelism):把每一个任务分配给每一个处理器独立完成。在同一时间点,任务一定是同时运行。并发不是并行。并行是让不同的代码片段同时在不同的物理处理器上执行。并行的关键是同时做很多事情,而并发是指同时管理很多事情,这些事情可能只做了一半就被暂停去做别的事情了。在很多情况下,并发的效果比并行好,因
2021-09-05 21:27:24
171
转载 Go语言GOMAXPROCS(调整并发的运行性能)
在 Go语言程序运行时(runtime)实现了一个小型的任务调度器。这套调度器的工作原理类似于操作系统调度线程,Go 程序调度器可以高效地将 CPU 资源分配给每一个任务。传统逻辑中,开发者需要维护线程池中线程与 CPU 核心数量的对应关系。同样的,Go 地中也可以通过 runtime.GOMAXPROCS() 函数做到,格式为:runtime.GOMAXPROCS(逻辑CPU数量)这里的逻辑CPU数量可以有如下几种数值:<1:不修改任何数值。 =1:单核心执行。 >1:多核并发
2021-09-05 21:24:49
396
转载 Go语言竞争状态简述
有并发,就有资源竞争,如果两个或者多个 goroutine 在没有相互同步的情况下,访问某个共享的资源,比如同时对该资源进行读写时,就会处于相互竞争的状态,这就是并发中的资源竞争。并发本身并不复杂,但是因为有了资源竞争的问题,就使得我们开发出好的并发程序变得复杂起来,因为会引起很多莫名其妙的问题。下面的代码中就会出现竞争状态:package main import ( "fmt" "runtime" "sync" ) var ( count int32 wg sync
2021-09-05 21:22:50
164
转载 Go语言并发通信
事实上,不管是什么平台,什么编程语言,不管在哪,并发都是一个大话题。并发编程的难度在于协调,而协调就要通过交流,从这个角度看来,并发单元间的通信是最大的问题。在工程上,有两种最常见的并发通信模型:共享数据和消息。共享数据是指多个并发单元分别保持对同一个数据的引用,实现对该数据的共享。被共享的数据可能有多种形式,比如内存数据块、磁盘文件、网络数据等。在实际工程应用中最常见的无疑是内存了,也就是常说的共享内存。先看看我们在C语言中通常是怎么处理线程间数据共享的,代码如下所示。#include
2021-09-05 21:21:52
177
转载 Go语言goroutine(轻量级线程)
在编写 Socket 网络程序时,需要提前准备一个线程池为每一个 Socket 的收发包分配一个线程。开发人员需要在线程数量和 CPU 数量间建立一个对应关系,以保证每个任务能及时地被分配到 CPU 上进行处理,同时避免多个任务频繁地在线程间切换执行而损失效率。虽然,线程池为逻辑编写者提供了线程分配的抽象机制。但是,如果面对随时随地可能发生的并发和线程处理需求,线程池就不是非常直观和方便了。能否有一种机制:使用者分配足够多的任务,系统能自动帮助使用者把任务分配到 CPU 上,让这些任务尽量并发运作。这种机
2021-09-05 21:19:43
133
转载 Go语言并发简述(并发的优势)
有人把Go语言比作 21 世纪的C语言,第一是因为Go语言设计简单,第二则是因为 21 世纪最重要的就是并发程序设计,而 Go 从语言层面就支持并发。同时实现了自动垃圾回收机制。Go语言的并发机制运用起来非常简便,在启动并发的方式上直接添加了语言级的关键字就可以实现,和其他编程语言相比更加轻量。下面来介绍几个概念:进程/线程进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。线程是进程的一个执行实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本..
2021-09-05 21:17:04
182
转载 Go语言strconv包:字符串和数值类型的相互转换
在实际开发中我们往往需要对一些常用的数据类型进行转换,如 string、int、int64、float 等数据类型之间的转换,Go语言中的 strconv 包为我们提供了字符串和基本数据类型之间的转换功能。strconv 包中常用的函数包括 Atoi()、Itia()、parse 系列函数、format 系列函数、append 系列函数等,下面就来分别介绍一下。string 与 int 类型之间的转换字符串和整型之间的转换是我们平时编程中使用的最多的,下面就来介绍一下具体的操作。Itoa():
2021-09-05 20:56:57
386
转载 Go语言运算符的优先级
运算符是用来在程序运行时执行数学或逻辑运算的,在Go语言中,一个表达式可以包含多个运算符,当表达式中存在多个运算符时,就会遇到优先级的问题,此时应该先处理哪个运算符呢?这个就由Go语言运算符的优先级来决定的。比如对于下面的表达式:var a, b, c int = 16, 4, 2d := a + b*c对于表达式a + b * c,如果按照数学规则推导,应该先计算乘法,再计算加法;b * c的结果为 8,a + 8的结果为 24,所以 d 最终的值也是 24。实际上Go语言也是这样处理的,先计
2021-09-05 20:55:54
445
转载 Go语言关键字与标识符简述
Go语言的词法元素包括 5 种,分别是标识符(identifier)、关键字(keyword)、操作符(operator)、分隔符(delimiter)、字面量(literal),它们是组成Go语言代码和程序的最基本单位。本节我们主要来介绍一下Go语言中的关键字和标识符。关键字关键字即是被Go语言赋予了特殊含义的单词,也可以称为保留字。Go语言中的关键字一共有 25 个:break default func interface select case ..
2021-09-05 20:54:50
190
转载 Go语言注释的定义及使用(godoc工具提取注释内容)
注释在程序中的作用是对程序进行注解和说明,便于对源码的阅读。编译系统在对源代码进行编译时会自动忽略注释的部分,因此注释对于程序的功能实现不起任何作用。在源码中适当地添加注释,能够提高源码的可读性。Go语言的注释主要分成两类,分别是单行注释和多行注释。单行注释简称行注释,是最常见的注释形式,可以在任何地方使用以//开头的单行注释; 多行注释简称块注释,以/*开头,并以*/结尾,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。单行注释的格式如下所示//单行注释多行注释的格
2021-09-05 20:50:16
778
转载 Go语言type关键字(类型别名)
类型别名是 Go 1.9 版本添加的新功能,主要用于解决代码升级、迁移中存在的类型兼容性问题。在 C/C++语言中,代码重构升级可以使用宏快速定义一段新的代码,Go语言中没有选择加入宏,而是解决了重构中最麻烦的类型名变更问题。在 Go 1.9 版本之前定义内建类型的代码是这样写的:type byte uint8 type rune int32而在 Go 1.9 版本之后变为:type byte = uint8 type rune = int32这个修改就是配合类型别名...
2021-09-05 20:49:23
168
转载 Go语言模拟枚举(const和iota模拟枚举)
Go语言现阶段没有枚举类型,但是可以使用 const 常量配合上一节《Go语言常量》中介绍的 iota 来模拟枚举类型,请看下面的代码:type Weapon int const ( Arrow Weapon = iota // 开始生成枚举值, 默认为0 Shuriken SniperRifle Rifle Blower ) // 输出所有枚举值 fmt.Println(Arrow, Shuriken, SniperRifle, Rifle, Blower) /
2021-09-05 20:46:30
665
1
转载 Go语言常量和const关键字
Go语言中的常量使用关键字 const 定义,用于存储不会改变的数据,常量是在编译时被创建的,即使定义在函数内部也是如此,并且只能是布尔型、数字型(整数型、浮点型和复数)和字符串型。由于编译时的限制,定义常量的表达式必须为能被编译器求值的常量表达式。常量的定义格式和变量的声明语法类似:const name [type] = value,例如:const pi = 3.14159 // 相当于 math.Pi 的近似值在Go语言中,你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断
2021-09-05 20:43:43
268
转载 Go语言变量的生命周期
在讨论变量生命周期之前,先来了解下计算机组成里两个非常重要的概念:堆和栈。变量的生命周期我们将在下一节《变量生命周期》中为大家讲解。什么是栈栈(Stack)是一种拥有特殊规则的线性表数据结构。1) 概念栈只允许从线性表的同一端放入和取出数据,按照后进先出(LIFO,Last InFirst Out)的顺序,如下图所示。图:栈的操作及扩展往栈中放入元素的过程叫做入栈。入栈会增加栈的元素数量,最后放入的元素总是位于栈的顶部,最先放入的元素总是位于栈的底部。从栈中取出元素...
2021-09-04 11:25:53
427
转载 Go语言变量逃逸分析
在讨论变量生命周期之前,先来了解下计算机组成里两个非常重要的概念:堆和栈。变量的生命周期我们将在下一节《变量生命周期》中为大家讲解。什么是栈栈(Stack)是一种拥有特殊规则的线性表数据结构。1) 概念栈只允许从线性表的同一端放入和取出数据,按照后进先出(LIFO,Last InFirst Out)的顺序,如下图所示。图:栈的操作及扩展往栈中放入元素的过程叫做入栈。入栈会增加栈的元素数量,最后放入的元素总是位于栈的顶部,最先放入的元素总是位于栈的底部。从栈中取出元素...
2021-09-04 11:23:44
194
转载 Go语言指针详解
与Java和 .NET 等编程语言不同,Go语言为程序员提供了控制数据结构指针的能力,但是,并不能进行指针运算。Go语言允许你控制特定集合的数据结构、分配的数量以及内存访问模式,这对于构建运行良好的系统是非常重要的。指针对于性能的影响不言而喻,如果你想要做系统编程、操作系统或者网络应用,指针更是不可或缺的一部分。指针(pointer)在Go语言中可以被拆分为两个核心概念:类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。 切片,由指..
2021-09-04 11:22:19
173
转载 Go语言数据类型转换
在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。由于Go语言不存在隐式类型转换,因此所有的类型转换都必须显式的声明:valueOfTypeB = typeB(valueOfTypeA)类型 B 的值 = 类型 B(类型 A 的值)示例:a := 5.0b := int(a)类型转换只能在定义正确的情况下转换成功,例如从一个取值范围较小的类型转换到一个取值范围较大的类型(将 int16 转换为 int32)。当从一个取值范围较大的类型转换到取值范围较小的类型时(将 int3
2021-09-04 11:20:50
131
转载 Go语言字符类型(byte和rune)
字符串中的每一个元素叫做“字符”,在遍历或者单个获取字符串元素时可以获得字符。Go语言的字符有以下两种:一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符。 另一种是 rune 类型,代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型。byte 类型是 uint8 的别名,对于只占用 1 个字节的传统 ASCII 编码的字符来说,完全没有问题,例如 var ch byte = 'A'
2021-09-04 11:19:49
212
转载 Go语言字符串
一个字符串是一个不可改变的字节序列,字符串可以包含任意的数据,但是通常是用来包含可读的文本,字符串是 UTF-8 字符的一个序列(当字符为 ASCII 码表上的字符时则占用 1 个字节,其它字符根据需要占用 2-4 个字节)。UTF-8 是一种被广泛使用的编码格式,是文本文件的标准编码,其中包括 XML 和 JSON 在内也都使用该编码。由于该编码对占用字节长度的不定性,在Go语言中字符串也可能根据需要占用 1 至 4 个字节,这与其它编程语言如C++、Java或者Python不同(Java 始终...
2021-09-04 11:18:40
462
转载 Go语言bool类型(布尔类型)
一个布尔类型的值只有两种:true 或 false。if 和 for 语句的条件部分都是布尔类型的值,并且==和<等比较操作也会产生布尔型的值。一元操作符!对应逻辑非操作,因此!true的值为 false,更复杂一些的写法是(!true==false) ==true,实际开发中我们应尽量采用比较简洁的布尔表达式,就像用 x 来表示x==true。var aVar = 10 aVar == 5 // false aVar == 10 // true aVar != 5 // tr..
2021-09-04 11:17:34
850
转载 Go语言复数
在计算机中,复数是由两个浮点数表示的,其中一个表示实部(real),一个表示虚部(imag)。Go语言中复数的类型有两种,分别是complex128(64 位实数和虚数)和complex64(32 位实数和虚数),其中complex128 为复数的默认类型。复数的值由三部分组成 RE + IMi,其中 RE 是实数部分,IM 是虚数部分,RE 和 IM 均为 float 类型,而最后的 i 是虚数单位。声明复数的语法格式如下所示:var name complex128 = complex(...
2021-09-04 11:16:43
700
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人