- 博客(45)
- 收藏
- 关注
原创 真希望你也明白runtime.Map和sync.Map
哈希表是计算机中最有用的数据结构之一。提供快速查找、添加和删除。Go 提供了一个实现哈希表的内置Map类型。
2022-12-13 09:01:36
405
1
原创 底层逻辑-理解Go语言的本质
上图已经展示了这个过程:从Java的源代码编译成jar包或war包(字节码),最终运行在JVM中。我们把Java源代码编译后的jar包或war包看成是工程师生产出来的产品,操作系统是一个平台,JVM就是中间商,那程序的整体性能也要受到中间商JVM的因素影响了。我们把Go语言的源代码编译后,生成二进制文件,直接就可以在操作系统上运行,没有中间商。优点:每种编程语言都有自己的Runtime, 把这个单词拆开来看,Run=运行,Time=时间,简称:运行时。Go语言的Runtime作用:Go语言的运行时,是和源代
2022-12-05 09:00:14
450
原创 20.Go-头等函数
Go 语言拥有,头等函数是指函数可以被当作变量一样使用,即函数可以被当作参数传递给其他函数,可以作为另一个函数的返回值,还可以被赋值给一个变量。
2022-09-14 11:38:58
230
原创 19.Go-make和new
内置函数new分配内存。该函数只接受一个参数,该参数是一个任意类型(包括自定义类型),而不是值,返回指向该类型新分配零值的指针。使用new函数首先会分配内存,并设置类型零值,最后返回指向该类型新分配零值的指针。
2022-09-14 11:38:02
105
原创 18.Go-错误与异常
使用errors包中的New函数可以创建自定义错误。下面是errors包中New是一个结构体类型,只有一个字符串字段s。它使用了指针接受者,来实现error接口的方法。New函数有一个字符串参数,通过这个参数创建了类型的变量,并返回了它的地址。于是它就创建并返回了一个新的错误。return 0 , errors . New("计算错误, 长度或宽度,不能小于0.") } return a * b , nil } func main() {= nil {计算错误 , 长度或宽度,不能小于 0.
2022-09-14 11:37:50
204
原创 17.Go-线程同步
在 Go 语言中,经常会遇到并发的问题,当然我们会优先考虑使用通道,同时 Go 语言也给出了传统的解决方式和来处理竞争条件。
2022-09-14 11:37:38
216
原创 16.Go-Select
语句用在多个发送/接收通道操作中进行选择。selectselectselect下面是使用上面的程序创建了 3 个通道,并在执行select语句之前往通道 1 、通道 2 和 通道 3 分别发送数据,在执行select语句时,如果有机会的话会运行所有表达式,只要其中一个通道接收到数据,那么就会执行对应的case代码,然后退出。
2022-09-14 11:37:22
168
原创 14.Go-协程
是与其他函数或方法一起并发运行的工作方式。协程可以看作是轻量级线程。与线程相比,创建一个协程的成本很小。因此在 Go 应用中,常常会看到会有很多协程并发地运行。
2022-09-14 11:36:54
292
原创 12.Go-方法
其实就是一个函数,在func这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。上面的代码片段创建了一个接收器类型为Type的方法methodName。
2022-09-14 11:36:03
64
原创 10.Go-包
用于组织 Go 源代码,提供了更好的可重用性与可读性。Go 语言有超过 100 个的标准包,可以用命令查看标准包的具体数目,标准库为大多数的程序提供了必要的基础组件。
2022-09-13 21:01:02
121
原创 09.Go-函数
是基于功能或逻辑进行封装的可复用的代码结构。将一段功能复杂、很长的一段代码封装成多个代码片段(即函数),有助于提高代码可读性和可维护性。由于 Go 语言是编译型语言,所以函数编写的顺序是无关紧要的。
2022-09-13 20:59:19
169
原创 08.Go-结构体
在 Go 中无法在结构体内部定义方法,这一点与 C 语言类似。package main import "fmt" // Lesson 定义一个名为 Lesson 的结构体 type Lesson struct {name , target string spend int } // PrintPersonInfo 定义一个与 Person 的绑定的方法 func(l Lesson) ShowLessonInfo() {
2022-09-13 20:58:03
390
原创 07.Go-指针
指针也是一种类型,也可以创建变量,称之为指针变量。指针变量的类型为*Type,该指针指向一个Type类型的变量。指针变量最大的特点就是存储的某个实际变量的内存地址,通过记录某个变量的地址,从而间接的操作该变量。
2022-09-13 20:56:20
154
原创 06.Go-容器类型
指针指向第一个 slice 元素对应的底层数组元素的地址,要注意的是 slice 的第一个元素并不一定就是数组的第一个元素。简单的讲,容量就是从创建切片索引开始的底层数组中的元素个数,而长度是切片中的元素个数。切片是对数组的一个连续片段的引用,所以切片是一个引用类型。切片 本身不拥有任何数据,它们只是对现有数组的引用,每个切片值都会将数组作为其底层的数据结构。当新的元素被添加到切片时,如果容量不足,会创建一个新的数组。当数组赋值给一个新的变量时,该变量会得到一个原始数组的一个副本。所有可比较的类型,如。
2022-09-13 20:55:05
146
原创 05.Go-基础数据类型
在静态类型语言(C++/Java/Golang 等)中规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存。
2022-09-13 20:53:51
97
原创 04.Go-变量与常量
iota 在 const 关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。关键字是 Go 语言中预先保留的单词,在程序中有特殊含义,不能用来定义变量或常量。方法三:在初始化的时候,可以省去数据类型,通过值去自动匹配当前变量的数据类型。定义一个常量,使用 const 关键字。iota 是 Go 语言的常量计数器,只能在常量的表达式中使用。声明变量的一般形式是使用 var 关键字。
2022-09-13 20:52:46
90
原创 03.Go-第一个Go程序
main 函数只能声明在 main 包中,不能声明在其他包中,并且,一个 main 包中也必须有且仅有一个 main 函数。代码第 4 行导入了 fmt 包,这行代码会告诉 Go 编译器,我们需要用到 fmt 包中的函数或者变量等,fmt 包是 Go 语言标准库为我们提供的,用于格式化输入输出的内容,类似的还有 os 包、io 包等。另外有一点需要注意,导入的包中不能含有代码中没有使用到的包,否则 Go 编译器会报编译错误,例如。来作为结束符,Go 编译器会自动帮我们添加,当然,在这里加上。
2022-09-13 20:51:53
100
原创 02.Go-开发环境搭建
工欲善其事,必先利其器”,做好一件事,准备工作非常重要。在开始学习 Go 技术之前,先介绍如何搭建 Go 开发环境是非常重要的一件事。
2022-09-13 20:50:36
236
原创 01.Go-开篇综述
Go 语言由谷歌(Google)公司于 2009 年正式对外发布,设计 Go 语言的初衷都是为了满足 Google 公司的需求。主要目标是“兼具 Python 等动态语言的开发速度和 C/C++等编译型语言的性能与安全性”,旨在不损失应用程序性能的情况下降低代码的复杂性,具有“部署简单、并发性好、执行性能好”等优势。最主要还是为了并发而生,并发是基于goroutine的,goroutine类似于线程,但并非线程,可以将goroutine理解为一种轻量级线程。Go 语言运行时会参与调度goroutine。
2022-09-13 17:01:42
171
原创 同样都是使用接口,JAVA和Go差距咋就这么大呢?
这篇文章将描述代码中经常使用的抢占式接口模式,以及为什么我认为在Go中遵循这种模式通常是不正确的。什么是抢占式接口接口是一种描述行为的方式,存在于大多数类型语言中。抢占式接口是指开发人员在实际需要出现之前对接口进行编码。一个示例可能如下所示。type Auth interface { GetUser() (User, error)}type authImpl struct { // ...}func NewAuth() Auth { return &authImpl}
2021-06-22 16:14:32
358
原创 Go Runtime的调度器
以goroutine形式进行Go并发编程是一种非常方便的方法,但有没有想过他是如何有效地运行这些goroutine?下面从设计的角度,深入了解和研究Go运行时调度程序,以及如何在性能调试过程中使用它来解释Go程序的调度程序跟踪信息。要了解为什么需要有一个运行时的调度以及它是如何工作的,先要回到操作系统的历史上,在这里将找到答案,因为如果不了解问题的根源。操作系统的历史单用户(无操作系统)批处理 单编程 运行完成多程序多程序的目的是使CPU和I/O重叠。如何做到的呢?多批次IBM O
2021-06-16 19:06:32
139
原创 21 面试必问!Goroutine的调度原理
正常的执行顺序就是线性的,谁在前面,谁就先执行,但是并发能力,会让你的程序,可以由若干个代码片段组合而成,并且每个片段都是独立运行的。Go语言天生支持这种并发能力,而Goroutine就是Go原生支持并发的具体实现。无论是Go的运行时还是用户写的代码都是运行在Goroutine中。Goroutine是由Go运行时管理的轻量级线程。和操作系统线程相比,goroutine的资源占用和使用代价非常小。我们可以创建几百到十几万个goroutine,甚至更多。Go运行时负责对goroutine进行管理和调度。不要
2021-01-21 14:13:40
529
原创 13 理解包导入路径的含义
Go 语言是使用包(package)作为基本单元来组织源码的, Go 程序就是这些包链接起来而构建的。 与C 语言的头文件包含机制相比则是“先进”了许多。即便是每次编译都是从头开始。避免了 C 语言那种通过头文件分析依赖的巨大开销。Go 语言以包为基本构建单元的构建模型,依赖分析非常简单。一 构建过程Go 编译速度快从三个方面分析:1.Go 要求每个源文件在开头处显式地import所有依赖的包,Go编译器不必读取和处理整个文件就可以确定其依赖的包列表;2.Go 要求包之间不能存在循环依赖。由于无环
2021-01-21 13:51:08
232
原创 20.不要在函数参数中使用空接口
为什么要做这一节,有一些小伙伴,把一些代码给我看,说同时写了的代码,参数是interface{}空接口,看不懂,不知道是做什么的,那么我们下面就看看空接口当参数的是不是合适?// $GOROOT/src/io/io.gotype Reader interface { Read(p []byte) (n int, err error)}Go编译器通过分析该接口定义得到接口的名称信息以及其方法信息,此接口类型参数赋值时,编译器会根据这些信息对实参进行检查。如果函数或方法的参数类型为空接
2021-01-20 06:53:46
125
原创 19 小接口的妙用
1 Go推荐的”小接口"接口interface这个单词,其实翻译过来就是 契约。契约可以简单也可以复杂,Go语言选择了简单。1) Go语言的接口与实现子类是隐式的关系,不是像java语言那样,要显示的implements关键字实现,实现类只要实现接口中的方法集合的全部方法,就是自动实现了该接口。2) 小接口使用起来更加灵活。下面是标准库中的定义// $GOROOT/src/builtin/builtin.gotype error interface { Error() string}
2021-01-20 06:53:02
134
原创 18 接口-实现方法集合
1. 方法集合func ShowMethod(i interface{}) { v := reflect.TypeOf(i) elemTyp := v.Elem() n := elemTyp.NumMethod() if n == 0 { fmt.Printf("%s's 方法为空!\n", elemTyp) return } fmt.Printf("%s's 方法:\n", elemTyp) for j := 0
2021-01-20 06:52:33
146
原创 17. Go语言---方法是什么
方法声明func(接受者 类型/类型指针) 方法名(参数列表)(返回值列表{//方法体}通过接收者,上述方法被绑定到某个类型上了。上述方法就是类型的一个方法,通过类型或类型指针的实例调用该方法。var t Tt.MethodName(参数列表)var pt *T = &tpt.MethodName(参数列表)方法名首字母大写巨鼎是导出方法(公开的)方法名定义要和类型定义放在同一个包中。func (t T) X1() 等价 X1(t T)当接收者类型为T的时候,Go函数的参数
2021-01-20 06:52:02
104
原创 16.defer 让代码更清晰
一 defer是什么日常我们写如下的代码var mu sync.Mutexmu.Lock()count++mu.Unlock()这样的代码特点就是在函数中会申请一些资源并在函数退出前释放或关闭资源。函数的实现需要资源在函数退出时被及时地释放,无论函数的执行时按预期进行,还是抛错。为此,程序员需要对函数中的错误里特别关注,在错误处理时不能忘记释放资源。这样让程序员需要思考的问题就会增加。同时多个资源释放怎么办?多个资源抛错怎么办?这样的逻辑将变得十分复杂,代码可读性也会极大降低,那程序的健壮性也
2021-01-20 06:51:22
117
原创 15 Go语言:函数是“一等公民“
m *sync.Mutexm.Lock() ...m.Unlock()如果要改变共享变量的情况下,我们会使用lock和unlock方法。在函数退出时被及时正确地释放,无论函数的执行流是按预期顺利进行还是出现错误。1. defer 的运作机制只有在函数(和方法)内部才能使用 defer。 defer 关键字后面只能接函数(或方法),这些函数被称为 deferred 函数。defer 将它们注册到其所在 goroutine 用于存放 deferred 函数的栈数据结构中,这些 defer
2021-01-20 06:50:36
166
原创 14.init你用对了吗?
在 Go 语言中,通过包的 init 函数来完成初始化的工作。1. init 函数Go 语言中有两个特殊的函数:1) main 包中的 main 函数,它是所有 Go 可执行程序的入口函数;2) 包级别的 init 函数。init 函数是一个无参无返回值的函数:func init() { ...}如果一个包定义了 init 函数,Go 运行时会负责在该包初始化时调用它的 init 函数。我们不能显式调用 init,否则会在编译期间报错。一个 Go 包可以拥有多个 ini
2021-01-20 06:49:31
519
原创 12.Go 字符串
内置的 string 类型。无论是字符串常量、字符串变量还是出现的字符串字面值,都被统一设置为 string。const ( s = “Hello")func main() { var s1 string = “Golang" fmt.Printf("%T\n", s) // string fmt.Printf("%T\n", s1) // string fmt.Printf("%T\n", “Cool Golang"
2021-01-20 06:49:04
95
原创 11.深入理解切片(slice)
slice是 Go 语言在数组之上提供的一个重要的抽象数据类型。在绝大多数需要使用数组的场合,切片都实现了完美替代。并且和数组相比,切片提供了更通用、功能更强大且便捷的数据序列访问接口。1.什么是数组Go 语言数组是一个固定长度的、容纳同构类型元素的连续序列。因此 Go 数组类型具有两个属性:元素类型和数组长度。但凡这两个属性相同的数组类型是等价的。比如下面变量 a、b、c 对应的数组类型是三个不同的数组类型:var a [8]stringvar b [8]bytevar c [9]string
2021-01-20 06:48:11
840
原创 10.零值可用
1. Go 类型的零值当通过声明或调用new为变量分配存储空间,或者通过复合文字字面量或make调用创建新值,并且还不提供显式初始化的情况下,Go会为变量或值提供默认值。Go 语言的每种原生类型都有其默认值,这个默认值就是这个类型的零值。内置零值如下:所有整型类型:0浮点类型:0.0布尔类型:false字符串类型:""指针、interface、slice、channel、map、function:nil数组、结构体等类型的零值初始化就是对其组成元素逐一进行零值初始化。2. 零值可用例子
2021-01-19 20:05:03
120
原创 09.枚举常量
iota 是 Go 语言提供的预定义标识符,它表示的含义是 const 声明块(包括单行声明)中每个常量所处位置在块中的偏移量(从零开始)。同时,每一行中的 iota 自身也是一个无类型常量。// $GOROOT/src/sync/mutex.goconst ( mutexLocked = 1 << iota // iota 的值是在 const 块中的偏移,因此 iota 的值为 0,我们得到 mutexLocked 这个常量的值为 1 <<
2021-01-19 20:00:24
205
原创 08.无类型常量
1. Go 常量使用常量定义的关键字const。Go 中所有与常量有关的声明都使用const。// $GOROOT/src/os/file.goconst ( // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified. O_RDONLY int = syscall.O_RDONLY // open the file read-only. O_WRONLY int = syscall.O_WRONLY //
2021-01-19 19:57:21
162
原创 07.变量声明须一致
Go 语言,使用变量之前需要先进行变量的声明。var s string = “Golang"n := 666Go 语言有两类变量包级别(package varible):在 package 级别可见的变量。如果是导出变量,该变量也可以被视为全局变量;局部变量(local varible):函数或方法体内声明的变量,仅在函数或方法体内可见。1. 包级别变量包级变量使用var 关键字的变量声明形式,从变量声明的时候是否延迟初始化这个角度对包级变量进行一次分类。1). 声明并同时显式初始化 /
2021-01-19 19:52:09
524
原创 06.命名惯例-见名知意
日常工作中,命名这件事看似简单,如果在大规模软件开发中,做出好的命名并非易事。命名是编程语言的要求:好的命名是为了提高程序的可读性和可维护性。什么是好的命名呢?无论哪门编程语言,良好的命名应该遵循一些通用的原则,不同编程语言在命名上还会有一些个性化的命名习惯。要想做好 Go 标识符命名(包括 package 命名),最少要遵循两个原则:1 简单且一致2 利用上下文辅助命名1. 简单且一致对于简单,我们最直观地理解就是越短越好,但这里的简单还包含着清晰明确。短意味着能用一个单词命名的,就不要使用单
2021-01-19 13:13:51
887
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人