自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

YJingLee's CSDN Blog

我的Blog→→→→ http://lyj.cnblogs.com←←←←

  • 博客(102)
  • 收藏
  • 关注

原创 工具:常用工具

2020-10-28 16:10:28 239 1

原创 工具:Go 工具链

2020-10-28 16:10:28 255

原创 前言:Go 文档之外,学习 Go 会遇到哪些问题?

我一直从事服务器后端系统开发快 10 年了,高并发分布式是互联网应用的基础,工作中先后使用过C#、Java、Go 等语言。当前工作需要把平台迁移到 Go,从零开始构建基础设施框架,在基础设施框架上开发各种业务系统。在迁移过程中逐步自研了一套功能完善的基础框架,同时也对语言的一些特性有了更深入的了解,所以便有了这个专栏。这个专栏的目的是如何把一门语言学精通了,什么叫精通,就是该会的东西都会了,让读...

2020-10-28 16:10:28 205

原创 测试:单元测试、性能测试、代码覆盖率、数据竞争、性能调优

测试是什么一个完整的软件有两个方面组成,第一是面向普通用户的软件产品,第二是面向公司的代码产品。代码需要不停更新迭代,也是一个产品。测试用于监管代码质量,测试本身也是算法,测试代码也需要维护和升级,测试和代码是相辅相成的。程序是算法加数据。简单的逻辑是一些算法指令,算法执行过程当中需要数据,这个数据可能在数据库里、也可能在文件里,算法和数据分离。测试也是,测试逻辑和测试数据分离。测试数据是场...

2020-10-28 16:10:27 352

原创 工具:GDB 调试器、常用工具、Go 工具链

工具链了解内置和扩展工具使用。开发环境安装及设置编译器(compile)和链接器(link)参数配套工具使用(get、vet)单元测试(testing)和性能工具(benchmark)调试器(dlv)及扩展工具(linter)使用安装$ GOROOT_BOOTSTRAP=/usr/local/go1.4 ./make.bash使用 apt、apk 安装(版本老旧)下载预...

2020-10-28 16:10:27 209

原创 动态:CGO

CGO混合编程,在 Go 和 C 代码间相互调用:CGO 不是 Go直接在 Go 源文件内嵌入 C 代码直接编译(链接)C 源码文件导入动态库(.so)混合编程很常见,现在很多项目使用不同语言也是一种混合编程,只不过很少基于编译器混合编程。编译分成编译和链接部分。编译前端生成 .obj 文件,链接器生成可执行文件。换句话说,无论前端是什么语言,使用不同的前端翻译成同样格式的 ob...

2020-10-28 16:10:26 194

原创 动态:反射

动态行为动态语言没有反射的概念,因为动态语言按照名称或者符号表寻址,它的一切都是动态的。那么为什么出现反射这种技术呢?是因为静态语言在动态行为上有很大不足。泛型不属于动态行为。泛型本身是一种基于模板的机制,相当于带有占位符的代码模板交给编译器 JIT 翻译,用具体类型替换占位符生成多套不同的代码。动态通常是运行期的行为,一般用于调整算法、数据结构、解析未知的数据。注意解析 XML 或者 JS...

2020-10-28 16:10:25 546

原创 动态:动态语言

动态嵌入动态除了反射以外,还有另外一种实现方式,就是在程序中直接嵌入 Lua、V8 等动态语言引擎。大多数语言都有类似嵌入包,比如 Go 语言有 go-duktape、otto、golua、gopher-lua。嵌入 Python 动态语言比较少,因为 Python 引用计数机制比较麻烦,而且 Python 运行时环境太大不是基于嵌入设计。Lua 本身天生基于嵌入设计的,实现复杂的动态逻辑...

2020-10-28 16:10:25 195

原创 组织:工作空间

项目目录组织(namespace)大多数人对于工作空间的概念依赖某些框架、某些工具定义好的生成规则,这种规则最早来源 IDE 时代。比如我们用 VS 创建一个项目 VS 创建对应的工作空间,创建各种各样的目录,很多时候只是往命名空间里添加文件,很少真正意义上的组织工作空间目录。很多操作系统源码对工具的依赖很低,它的目录组织都是基于人工的。对于项目管理需要摆脱工具或者框架的规则,换一种方式去管理...

2020-10-28 16:10:24 467

原创 组织:访问权限

访问权限封装的思想就是把一些状态打包只看到该看到的东西。我们把程序分为不同的类型和包,就出现是否允许访问的问题,甚至出现在同一个命名空间是否允许访问的问题。不同的语言对于访问权限做法不一样,C 语言没有访问权限的概念,所有的方法都可以通过头文件的符号访问。访问权限控制是编译器的概念。编译器通过识别访问权限,决定代码调用是否合法,编译是否成功。因为语言访问权限和基于文件系统或者操作系统的访问权...

2020-10-28 16:10:24 145

原创 标准库:Web

33.1 Web 框架现在大家做的大部分工作都和 Web 开发有关系,我们学习的不是怎么使用 Go 语言来写一个 Web 程序,我们关键是通过 Web 开发分清楚对于一个复杂的系统我们要去怎么样去鉴定各自的边界,我们知道 Web 开发包含的内容非常的多,我们需要做的是怎么样把这些功能整合到一起,它们各自边界是什么,它们各自相关代码的流程是什么,这些东西没有什么复杂度的问题,关键要搞清楚流程。我...

2020-10-28 16:10:23 162

原创 标准库:DB 数据库

数据库设计思想数据库设计是很典型的案例,通常我们用它作为学习的样本,在设计中有些模式也会被鉴戒或者被引入其他的领域。首先数据库本身是非常庞大而复杂的概念,跟数据库相关的东西很多,如何在不同类型数据库之间抽象出很好的设计是很难的事情。标准库提供的是 API 设计而不是框架设计,跟数据库相关的框架可能是利用辅助类型快速创建 SQL 语句,读写操作类似 ORM 框架,但是标准库并不会提供这些。任何一种...

2020-10-28 16:10:23 669

原创 标准库:IO

IO 操作我们在类 Unix 系统下大多数都是 IO 操作,比如 web 应用、数据库操作、文件读写,Linux 核心思想是把一切当作文件。IO 操作一般分为两套,一套是操作系统提供的系统 IO,一套是标准库提供的缓冲 IO。IO 操作不仅仅是读写数据,它提供的是所谓数据流的概念。不要提到 IO 就想到读写文件,很多东西都可以流化,它更像一种设计模式或者模型。数据流的核心是连续性的数据,数据...

2020-10-28 16:10:22 130

原创 标准库:Context

上下文上下文不太好理解,因为上下文在不同地方不同说法显得有点太过于抽象,多数情况下上下文指的是完成一个行为所需要的环境。这个行为可能是一段逻辑,也可能是某一个调用,甚至是进程和线程的切换,甚至是用户空间到系统空间的切换。这个环境可能包含保存寄存器相关的执行信息,这些信息确保行为可以正常执行或者回溯。也就是说在不同的场合有明确的定义,但是我们很难把它具象化,需要根据上下文来判断上下文。就 cont...

2020-10-28 16:10:22 155

原创 并发:同步

同步概况同步是并发最后一个环节。当两个并发单元共享同一个数据的时候需要同步处理。这里的并发单元不限于进程中的两个线程,也可能两个进程,甚至两台服务器。同步处理不局限共享同一块内存,当两个进程共享同一个文件给文件加锁都是同步处理,在数据库中启动一个事务或者启动乐观锁都是同步处理。共享同一资源产生数据竞争都需要做同步处理。标准库 sync 包专门用来做同步的,它由条件、锁,锁分为互斥和读写,Wa...

2020-10-28 16:10:21 335

原创 并发:并发任务单元

并发任务单元go func(s string) {println(s) }("hello")go 语句创建并发任务单元(goroutine),并打包函数执行所需参数。并发任务稍后由调度器调度执行。进程内所有用户代码均以 goroutine 方式执行。创建 goroutine 后,不阻塞。任务单元自带栈内存(2KB-1GB)。Go 语言写并发非常容易,因为所有的用户代码都是...

2020-10-28 16:10:20 193

原创 并发:通道

编程就是把具体实现抽象,屏蔽底层的一些细节。数据就像一条流水线,从一个并发单元传递到另一个并发单元。那么我们怎么传递数据呢?基于内存共享或者基于网络传输?数据共享方式同一进程内有不同的并发单元,例如 goroutine A 和 goroutine B,它们可能在不同的物理核上并发执行,如果访问同一个变量数据,A 读写数据时 B 不能写入,同理 B 读写数据时 A 就不能写入,否则会产生数据竞...

2020-10-28 16:10:20 228

原创 运行时:系统监控

系统监控本身是一种守护方式来确保有些事情必须要处理。系统监控的用途现在很多编程框架都是基于 epoll 来实现异步方式,但是我们有个程序对 epoll 做检查,这种检查要不自己执行,要么写个定时器定期的扫描,然后看看有哪些句柄是返回的。只不过这东西在 Go 的 runtime 是系统监控做这件事。runtime 三大组件,内存分配器、垃圾回收器、goroutine 调度。实际上除此之外还有系...

2020-10-28 16:10:19 608

原创 并发:并发与并行

并发和并行了解并发 (concurrency) 和并行 (parallesim) 的区别。并发:逻辑上具备同时处理多个任务的能力。并行:物理上在同一时刻执行多个并发任务。并发是并行的基础,并行是并发的理想执行模式。单核(多线程)或单线程(协程)可通过任务切换实现并发。多线程和多进程是并行的必备条件。并发编程模型现在属于必备的知识。现代语言都在简化并发编程模型,并发编程本身也引发出...

2020-10-28 16:10:19 314

原创 运行时:并发调度

严格来说 goroutine 不能从字面层来翻译称之为协程,它实际上是一套相对完整的虚拟机。goroutine 模型Go 语言的 goroutine 模型相对来说设计的不错,goroutine 模型使用的是多对多模型。多对多模型被一些操作系统一些语言 Rust、Java 抛弃,而改用一对一模型,因为一对一模型性能高,但是对于海量的并发操作未必是最优秀的。Go 语言更适合 IO 密集型,对 C...

2020-10-28 16:10:18 201

原创 操作系统:协程和上下文切换

首先,我们明确一个观点:程序的用线程来执行的。同步执行序如上图用户线程执行的一段时间片,线程从起点 A 开始执行,执行用户代码到终点 B 结束,执行到 C 点需要执行系统调用,用户线程就会在 C 点阻塞,执行序进入系统内核状态,剩下的时间片在系统内核执行。执行系统调用是操作系统内核的异步调用,系统内核的时间片是由操作系统提供的内部时间片。系统调用不使用剩下的时间片,在用户线程阻塞,剩下的用...

2020-10-28 16:10:17 461

原创 运行时:内存分配器

我们在做架构设计的时候,时时刻刻记住抽象。早期编码没有驱动程序一说,屏幕显示文字则需要把数据写到显卡内存里输出,后来操作系统做一层抽象,我们不需要和硬件打交道,只和驱动程序API打交道。可以同时运行多个程序,操作系统基于时间片切换,从协作式调度变成抢占式调度,这其实也是抽象。运行时现代编程语言大部分有运行时,类似在操作系统之上再抽象出一层虚拟机,它接管着很多东西,比如内存、垃圾回收、甚至包含并...

2020-10-28 16:10:17 135

原创 运行时:垃圾回收器

垃圾回收器相当于程序手动释放内存,从引用计数到现代各种方式,它的理论基础并没有很大差别。Go 垃圾回收器源码不适合作为学习的范例。垃圾回收消耗最多的时间是扫描对象,看对象是否活着的,是不是有其他对象引用,有引用就是活着的没有引用就是死的。垃圾回收器不关心对象有多大,它关心是对象的数量,也就是对象数量越多垃圾回收扫描时间就会越长,怎么样才能让它每次扫描的数量少一点呢?代龄和垃圾清理两种机制都是为...

2020-10-28 16:10:17 129

原创 操作系统:进程与线程

进程、线程的区别在编程中最常见的三个概念是进程、线程、协程。程序包含一系列资源,比如代码、图片、音视频、安装文件,程序是为了运行一段代码所需资源的总和。进程严格上说也是资源的集合,相对于程序静态资源来说,进程大多是动态资源,比如运行期的虚拟内存空间,正在执行 CPU 缓存的数据,这些资源总和称之为进程,进程是一种资源单位,操作系统为资源单位做管理。线程是和 CPU 交互的,线程是由进程的组...

2020-10-28 16:10:16 166

原创 对象:接口转换和默认值

接口转换type Xer interface { A()}type X intfunc (X) A() {}func main() { var o X var e Xer = o a, ok := e.(X) println(a, ok)}func main() { var x interface{} = func(x int) s...

2020-10-28 16:09:29 191

原创 对象:接口性能损失

接口性能损失type Xer interface { A(a int)}type X intfunc (X) A(b int) { println("a") }func main() { var o X var e Xer = &o o.A(1) e.A(1)}$ go build && go tool objdum...

2020-10-28 16:09:28 254

原创 对象:匿名接口、接口嵌入和行为

14 空接口func main() { var e interface{} = 1 println(e)} 空接口没有任何声明,所以所有类型都实现该接口。类似object单根祖先类型。空接口就是什么方法的声明都没有,意味着任何一个类型都能实现空接口。在其他语言里都有一个类似Object单根类型,什么类型都可以往里丢。14 匿名接口type X intfunc...

2020-10-28 16:09:28 395

原创 对象:接口思想和接口内部实现

接口接口(interface)代表一种“约定”或“协议”。允许在非显式关联的情况下,组合并调用其他类型的方法。接口是多个方法声明的集合。接口可解除依赖关系,屏蔽实现细节。只要方法集包含对应方法即为实现,无显式声明。类型可实现多个接口,以面向不同服务。调用一个对象的成员有两种方式,第一种是直接调用,另外一种方式是通过接口间接调用。接口代表一种行为上的约定或协议。接口是设计上的概念。...

2020-10-28 16:09:27 311

原创 对象:GDB 接口内部结构

5-12 gdb接口内部结构type N intfunc (N) A() { println("*N.A") }func (*N) B() { println("*N.B") }func (*N) C() { println("*N.C") } // *N = N + *N = A+B+C // N = Atype Ner interface { A() B()...

2020-10-28 16:09:27 196

原创 对象:方法集调用

方法集调用N类型,有两个方法,当我们用N类型调用的时候,理论上只执行String,但是如果我们用N类型调用Inc是不是合法的呢?type N intfunc (n *N) Inc() { *n++}func (n N) String() string { return strconv.Itoa(int(n))}func main() { var n N ...

2020-10-28 16:09:26 112

原创 对象:匿名嵌入方法集

匿名嵌入方法集嵌入S,T += receiver S。嵌入*S,T += receiver (S + *S)。嵌入S或*S, *T += receiver (S + *S)。匿名嵌入字段时基本规则大概这样。如果在一个类型里嵌入S,那么T的方法集包含S。如果嵌入*S那么包含全部。不管S还是*S,以*T的方式获取方法集的时候包含全部。所以用指针方式获取方法集时等于全部,当用T方式获取时,分...

2020-10-28 16:09:26 118

原创 对象:方法表达式汇编

方法表达式汇编现在研究Method Value究竟怎么实现的?它是怎么持有那两个数据的,另外这两个数据怎么保存下来的?怎么传递的?type N intfunc (n N) Print() { println(n)}func main() { var n N = 100 // instance p := &n // n.pointer ...

2020-10-28 16:09:25 89

原创 对象:匿名嵌入和匿名字段方法

匿名嵌入将其他类型匿名嵌入到复合类型,以组合方式获取方法调用权限。匿名类型字段实际以“类型”为名。不能同时嵌入T和*T。方法名存在遮蔽,以“最近”为准。组合和调用语法糖,不是继承。OOP三大基本规则封装继承多态,继承很多语言都放弃了,涉及到很多概念比如抽象类型、覆盖、重写。Go语言组合优先于继承。所谓的匿名嵌入就是没有给字段名字只给类型。然后用语法糖的概念来实现类似继承的概念。用...

2020-10-28 16:09:25 184

原创 对象:方法集定义

方法集思想理解接口首先需要理解方法集的概念,接口在不同语言里有不同的做法,静态语言往往会有显式的接口,就是声明一个接口类型,至于哪些类型是否实现了这个接口类型,不同语言有不同处理方法,C#或者Java必须指定类型实现了接口,Go语言只要符合条件就可以了,不需要显式的说实现。动态语言很多时候没有接口这样的概念,只要有对应的名字就可以了,它们把接口称之为协议,概念都是类似的,在了解接口之前,理解方法...

2020-10-28 16:09:25 236

原创 对象:锁对 receiver 的影响

receiver设定要修改数据状态,使用*T。无需修改状态的小对象或固定值,建议使用T。大对象使用*T,避免过高的参数复制成本。引用类型、字符串、函数等指针包装对象,直接使用T。包含锁(mutex)的复合结构,使用*T,避免锁被复制后失效。无法确定时使用*T,以维护唯一实例。到底用X还是用*X,什么情况用值,什么情况用指针?它们都属于X类型的方法,怎么选择有一些简单的规则。比如修...

2020-10-28 16:09:24 102

原创 对象:方法表达式

方法表达式按调用方式不同,方法可分为expression和value两种模式。表达式模式将方法视作普通函数,须显式传入receiver参数。值模式打包receiver和function,以便传递和稍后调用。方法本身可以看作函数,把函数赋值给一个变量很正常,同样的,方法也可以这样做,但是处理时候有两种方法,第一种用类型表达是一个普通的函数,因为它没有和实例相绑定,调用的时候必须显式的提供...

2020-10-28 16:09:24 498

原创 对象:方法隐式接收实例

02 隐式实例接收参数receiverGo限制是给一个类型定义方法只能在当前包,如果不是在当前包不能为它定义方法。像C#可以给标准库里面的类型增加扩展方法。Go涉及的思想基于的是包是个封闭状态,定义扩展方法实际上是侵入式设计。我们设计时候尽可能希望依赖关系变得很简单,因为多数时候我们并不需要把我们依赖的东西暴露出去。定义方法两种方式,第一种选择与接口类型相绑定pointer,还有一种选择与值类...

2020-10-28 16:09:23 114

原创 对象:方法调用和本质

5-3 方法调用和本质03 别名定义03 方法调用03 不能使用多级指针调用方法03 方法可被内联03 方法本质5-3 方法调用和本质03 别名定义type X inttype Y = X//go:noinlinefunc (x X) A() { println("X.A") }//go:noinlinefunc (y Y) B() { print...

2020-10-28 16:09:23 88

原创 数据:什么是指针?

指针三种指针相关数据结构。*p:普通指针。(强引用)unsafe.Pointer:无类型指针。(强引用)uintptr:存储地址的整数。(弱引用)go有三种方式的指针,第一种是普通指针,肯定是强引用。还有一种无类型指针或者万能指针,它也是强引用。第三种uintptr只是一个普通的整数,只是把目标对象地址存进来,它与目标对象之间没有任何关联,作用有点像弱类型。强引用对垃圾回收器造成影响...

2020-10-28 16:09:22 1028

原创 对象:方法 vs 函数

方法 vs 函数正确使用函数和方法,对于编码十分重要。函数是数据加工流程蓝图。引起函数变化的应该(最好)只有参数。方法面向数据,维护和展现其状态。多次调用或不同调用次序导致不同输出结果。多个方法共同维护状态,存在耦合和关联性。方法带来很多设计层面上的概念,方法可以看成是函数的一种包装,在实现层面方法是函数的语法糖。在汇编角度来看,方法和函数没多大区别,方法是高级语言语法糖。在设...

2020-10-28 16:09:22 254

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除