Go语言中文网 为您找到相关结果 558

Go语言atomic原子操作

atomic是最轻量级的锁,在一些场景下直接使用atomic包还是很有效的。 下面内容摘秒自《GO并发编程实战》—— 原子操作: CAS操作的优势是,可以在不形成临界区和创建互斥量的情况下完成并发安全的值替换操作。 这可以大大的减少同步对程序性能的损耗。 当然,CAS操作也有劣势。在被操作值被频繁变更的情况下,CAS操作并不那么容易成功。 原子操作共有5种,即:增或减、比较并交换、载入、存储和交换 1. 增或减 被用于进行增或减的原子操作(以下简称原子增/减操作)的函数名称都以“Add”为前缀,并后跟针对的具体类型的名称。 不过,由于atomic.AddUint32函数和atomic.AddUint64函数的第二个参数的类型分别是uint32和uint64,所以我们无法通过传递一个负的数值来...阅读全文

博文 2015-06-17 20:12:43 xcltapestry

【GoLang笔记】遍历map时的key随机化问题及解决方法

之前的一篇笔记曾分析过,Go的map在底层是用hashmap实现的。由于高效的hash函数肯定不是对key做顺序散列的,所以,与其它语言实现的hashmap类似,在使用Go语言map过程中,key-value的插入顺序与遍历map时key的访问顺序是不相同的。熟悉hashmap的同学对这个情况应该非常清楚。 所以,本文要提到的肯定不是这个,而是一个比较让人惊奇的情况,下面开始说明。 1. 通过range遍历map时,key的顺序被随机化 在golang 1.4版本中,借助关键字range对Go语言的map做遍历访问时,前后两轮遍历访问到的key的顺序居然是被随机化的! 这个现象在其它语言中是很少见的,比如C语言实现hashmap时,通常会用数组(即一段连续的内存空间)来存key,虽然key的...阅读全文

博文 2015-04-02 19:00:01 slvher

golang 内置函数new() 和struct{} 初始化的区别

new() 这是一个用来分配内存的内置函数,它的第一个参数是一个类型,不是一个值,它的返回值是一个指向新分配的 t 类型的零值的指针。 在golang的代码定义如下: func new(t Type) *Type strut{} 直接使用struct{} 来初始化strut时,返回的是一个struct类型的值,而不是指针两者是不一样的 两者对比代码如下: type Student struct{ id int name string } func main(){ var s_1 *Student = new(Student) s_1.id = 100 s_1.name = "cat" var s_2 Student = Student{id:1,name:"tom"} fmt.Println...阅读全文

博文 2015-06-17 20:03:41 happinessaflower

Golang百万级高并发实例

前言 感谢Handling 1 Million Requests per Minute with Go 这篇文章给予的巨大启发。 基础 我们使用Go语言,基本上是因为他原生支持的高并发:Goroutine 和 Channel;Go 的并发属于 CSP 并发模型的一种实现;CSP 并发模型的核心概念是:“不要通过共享内存来通信,而应该通过通信来共享内存”。 简单用法 我一开始学习Go语言的时候,遇到大访问量的时候,会先创建一个带缓冲的channel,然后起一个Go协程来逐个读取channel中的数据并处理。说他是并发是因为他没有占用主线程,而是另起了一个协程独自运行。但是这没有实现请求之间的并发。特别注意:Go语言中的map不是并发安全的,要想实现并发安全,需要自己实现(如加锁),或者使用sy...阅读全文

博文 2019-01-16 00:35:11 wz669

golang对共享内存的操作

不同进程间的内存是互相独立的,没办法直接互相操作对方内的数据,而共享内存则是靠操作系统提供的内存映射机制,让不同进程的一块地址空间映射到同一个虚拟内存区域上,使不同的进程可以操作到一块共用的内存块。共享内存是效率最高的进程间通讯机制,因为数据不需要在内核和程序之间复制。 共享内存用到的是系统提供的mmap函数,它可以将一个文件映射到虚拟内存的一个区域中,程序使用指针引用这个区域,对这个内存区域的操作会被回写到文件上,其函数原型如下: void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset); 参数fd为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定f...阅读全文

博文 2014-10-04 19:27:13 壬癸甲乙

Go语言slice的那些坑

Go语言Google开发的适用于多核编程的语言。我感觉它像是C语言的现代版本,简单,并发支持友好,部署轻松。GO语言中保留关键字就只有25个,这也足以说明它的学习成本并不高。 然而,Go语言里面slice这个东西并不简单。初学者容易掉入坑中。此文件就试图把slice给讲解清楚。 下面先讲一下slice的一些基本特性。 1. slice内部有三个变量,分别是:ptr, len, cap ptr是用来存储数据的数组 cap是ptr数组的长度 len是实际数组的长度 2. 如何在初始化的时候,指定slice的长度? a := make([]int, 10) 这里make的时候,第2个参数,就是这个slice的长度。 这个时候它的capacity是多少呢? fmt.Println(cap(a)) 这...阅读全文

博文 2016-03-31 19:00:05 zhanchenxing

golang中的append函数详解

1. append函数是用来在slice末尾追加一个或者多个元素。 2. 当追加元素时,发现slice的**len>cap**时,会重新开辟一个**2*cap**的内存空间去存储追加过元素的slice。 3. 如果追加元素后slice的**len<=cap**,则append返回的新生成的slice的内存地址**依旧**是传入的slice参数的内存地址。 ```go testSlice := make([]int, 0) testSlice = append(testSlice, 0) fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice), cap(testSlice), testSlice) //len: 1, cap: 1,...阅读全文

博文 2018-11-12 14:56:01 lijingtian

为什么我要选择erlang+go进行服务器架构

服务器非业余研究http://blog.csdn.net/erlib 作者Sunface 估计很多同学看到这里都会觉得迷惑,go的大名已经如雷贯耳了,但是erlang?这个东东是神马?难道是编程语言?怎么从来没听说过。 这里请允许我先介绍一下使用Erlang开发的比较有名的应用: 一:whatsapp 只凭32个技术人员,如何应付4.5亿的用户?对于刚刚被Facebook用190亿美元收购的WhatsApp来说,答案是Erlang——一种诞生于上世纪80年代的编程语言,终于在此时走到了聚光灯下。 这个应用把erlang的特性发挥到了极致,利用到了它最好的vm、 集群基础设施、数据库mnesia, 消除了非常多的数据Scale、内存池和锁的问题, 提到的技术和修正点非常值得我们参考。 虽然大部...阅读全文

博文 2015-02-23 23:00:00 robslove

Golang直接操作共享内存

前言 故事起源于要搭一个高性能的日志中心。当然使用了elk这一套。但是,对于logstash来说,它主要使用的是文件日志的方式了捕捉log。而写文件日志的话会非常慢。对于实时日志要处理滚动的日志更是这样,每次检查是否需要流动日志,然后打开日志,然后写入,然后关闭,当然这中间可以优化。这一切都是那么慢,发起了n个系统调用,硬盘寻道等。这时候想到了用共享内存来通信。 共享内存的基本知识 要使用共享内存要执行以下几步: 发起一个系统调用,让系统帮你生产一块内存,或者取得一块已经存在的内存来使用。 把内存attach到当前进程,让当前进程可以使用。大家都知道,我们在进程中访问的是虚拟内存地址,系统会把它映射到物理内存中。如果没有这一步,第1步创建的内存就不能在当前进程访问。 这时就可以对内存进程读写...阅读全文

博文 2017-07-02 16:10:18 tenfy

如何优雅地等待所有的goroutine退出

Table of Contents 1. 通过Channel传递退出信号 2. 使用waitgroup goroutine和channel是Go语言非常棒的特色,它们提供了一种非常轻便易用的并发能力。但是当您的应用进程中有很多goroutine的时候,如何在主流程中等待所有的goroutine 退出呢? 1 通过Channel传递退出信号 Go的一大设计哲学就是:通过Channel共享数据,而不是通过共享内存共享数据。主流程可以通过channel向任何goroutine发送停止信号,就像下面这样: func run(done chan int) { for { select { case <-done: fmt.Println("exiting...") done <- 1 break de...阅读全文

golang协程——通道channel阻塞

新的一年开始了,不管今天以前发生了什么,向前看,就够了。 说到channel,就一定要说一说线程了。任何实际项目,无论大小,并发是必然存在的。并发的存在,就涉及到线程通信。在当下的开发语言中,线程通讯主要有两种,共享内存与消息传递。共享内存一定都很熟悉,通过共同操作同一对象,实现线程间通讯。消息传递即通过类似聊天的方式。golang对并发的处理采用了协程的技术。golang的goroutine就是协程的实现。协程的概念很早就有,简单的理解为轻量级线程,goroutine就是为了解决并发任务间的通信而设计的。golang解决通信的理念是:不要通过共享内存来通信,而应该通过通信来共享内存。golang解决方案是消息传递机制,消息的传递就是通过channel来实现的。 channel的使用很简单,...阅读全文

博文 2016-02-16 03:00:01 xiaofengshuyu

玩转Golang之Struct结构体

先介绍一下go语言的类型系统 Golang中的类型系统 类型系统是指一个语言的类型体系结构。一个典型的类型系统通常包含如下基本内容:  基础类型,如byte、int、bool、float等;  复合类型,如数组、结构体、指针等;  可以指向任意对象的类型(Any类型);  值语义和引用语义;  面向对象,即所有具备面向对象特征(比如成员方法)的类型;  接口。 Go语言中的大多数类型都是值语义,并且都可以包含对应的操作方法。在需要的时候,你可以给任何类型(包括内置类型)“增加”新方法。而在实现某个接口时,无需从 该接口继承(事实上,Go语言根本就不支持面向对象思想中的继承语法),只需要实现该接口 要求的所有方法即可。任何类型都可以被Any类型引用。Any类型就是空接口,即inte...阅读全文

博文 2018-08-11 23:35:04 夏海社长

Golang数组Array

数组Array 定义数组的格式:var package main import ( "fmt" ) func main() { //数组的长度也是类型的一部分,因此具有不同长度的数组为不同类型 var a [2]int //定义长度为2的int型数组。 var b [1]int //长度为1的int型数组 b = a fmt.Println(b)//此时编译时不通过的 } 数组的长度也是类型的一部分,因此具有不同长度的数组为不同类型 package main import ( "fmt" ) func main() { a := [20]int{19: 1} //长度为20的int型数组,索引位为19的赋值为1 b := [...]int{0: 1, 1: 2, 2: 3} //3个点代表不...阅读全文

博文 2017-09-30 09:30:01 skymyyang

Golang slice 切片原理

golang 中的 slice 非常强大,让数组操作非常方便高效。在开发中不定长度表示的数组全部都是 slice 。但是很多同学对 slice 的模糊认识,造成认为golang中的数组是引用类型,结果就是在实际开发中碰到很多坑,以至于出现一些莫名奇妙的问题,数组中的数据丢失了。 下面我们就开始详细理解下 slice ,理解后会对开发出高效的程序非常有帮助。 这个是 slice 的数据结构,它很简单,一个指向真实 array 地址的指针 ptr ,slice 的长度 len 和容量 cap 。 其中 len 和 cap 就是我们在调用 len(slice) 和 cap(slice) 返回的值。 我们来按照 slice 的数据结构定义来解析出 ptr, len, cap // 按照上图定义的数据...阅读全文

golang make()内置函数

内建函数 make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),跟 new 类似,第一个参数也是一个类型而不是一个值,跟 new 不同的是,make 返回类型的引用而不是指针,而返回值也依赖于具体传入的类型 make()函数在golang的代码如下: func make(t Type,size IntegerType) Type 使用make来创建slice,map,chanel说明如下: slice: var slice_ []int = make([]int,5,10) fmt.Println(slice_) var slice_1 []int = make([]int,5) fmt.Println(slice_1) var s...阅读全文

博文 2015-06-17 20:03:47 happinessaflower

golang里channel的实现原理

channel是消息传递的机制,用于多线程环境下lock free synchronization. 它同时具备2个特性: 1. 消息传递 2. 同步 golang里的channel的性能,可以参考前一篇:http://blog.sina.com.cn/s/blog_630c58cb01016xur.html 此外,自带的runtime package里已经提供了benchmark代码,可以运行下面的命令查看其性能: go test -v -test.bench=".*" runtime 在我的pc上的结果是: BenchmarkChanUncontended 50000000 67.3 ns/op BenchmarkChanContended 50000000 67.7 ns/op Ben...阅读全文

Go语言 传值和传指针性能对比

载自达达的博客 以往的C编程经验告诉我们,指针传参会有更好的性能,在Go语言中,这条经验也是通用的。但是需要留意两个问题: 指针传参会导致参数的操作领域不确定,到底函数内部会不会改变传入的对象呢?Go语言中没有类型C那样的const关键字,所以无法控制。Go语言是有GC的,并且这个GC还不是很完善,受对象数量影响较大,传递指针意味着可能多创建不必要的对象,到底指针传参带来的性能提升能不能抵消创建对象产生的GC压力呢?这是一个不好观察到的数据。(原作者达达这里应该是有错误的,首先传值也是复制,要产生一个新对象,分配内存地址传到新的函数中,其次指针一般来说64个字节,复制的代价远小大中型数据传值,因此在都产生一个新对象的情况下,指针还是远优先于传大中型的值结构) 下面是性能消耗的测试代码: pa...阅读全文

博文 2014-10-09 18:00:00 abv123456789

Go的变量到底在堆还是栈中分配

Go的变量到底在堆还是栈中分配 2015-10-22 最近试着优化掉一些小对象分配,发现一个很诡异的问题:这段代码会在堆上分配对象! package main import ( "fmt" ) func main() { var a [1]int c := a[:] fmt.Println(c) } 看汇编代码 go tool compile -S test.golang "".main t=1 size=336 value=0 args=0x0 locals=0x98 0x0000 00000 (test.go:7) TEXT "".main(SB), $152-0 0x0000 00000 (test.go:7) MOVQ (TLS), CX 0x0009 00009 (test.go:...阅读全文

博文 2016-07-20 13:27:37 zenlife

golang学习之struct

结构体定义的一般方式如下: type identifier struct { field1 type1 field2 type2 ... } type T struct {a, b int} 也是合法的语法,它更适用于简单的结构体。 var t *T t = new(T) 变量 t 是一个指向 T的指针,此时结构体字段的值是它们所属类型的零值,使用 new 函数给一个新的结构体变量分配内存,它返回指向已分配内存的指针。 无论变量是一个结构体类型还是一个结构体类型指针,都使用同样的 选择器符(selector-notation) 来引用结构体的字段,即: type myStruct struct { i int } var v myStruct // v是结构体类型变量 var p *mySt...阅读全文

博文 2016-06-15 09:00:00 caiya928

Go并发原理

Go语言是为并发而生的语言,Go语言是为数不多的在语言层面实现并发的语言;也正是Go语言的并发特性,吸引了全球无数的开发者。 并发(concurrency)和并行(parallellism)并发(concurrency):两个或两个以上的任务在一段时间内被执行。我们不必care这些任务在某一个时间点是否是同时执行,可能同时执行,也可能不是,我们只关心在一段时间内,哪怕是很短的时间(一秒或者两秒)是否执行解决了两个或两个以上任务。 并行(parallellism):两个或两个以上的任务在同一时刻被同时执行。 并发说的是逻辑上的概念,而并行,强调的是物理运行状态。并发“包含”并行。 (详情请见:Rob Pike 的PPT) Go的CSP并发模型Go实现了两种并发形式。第一种是大家普遍认知的:多线...阅读全文

Go 语言的数据结构:链表

数据结构和算法是计算机科学的重要组成部分。虽然有时候它们看起来很吓人,但大多数算法都有简单的解释。同样,当问题能用算法来解释清楚的时候,算法的学习和应用也会很有趣。 这篇文章的目标读者是那些对链表感到不舒服的人,或者那些想要看到并学习如何用 Golang 构建一个链表的人。我们将看到如何通过一个(稍微)实际的例子来实现它们,而不是简单的理论和代码示例。 在此之前,让我们来谈谈一些理论。 ## 链表 链表是比较简单的数据结构之一。维基百科关于链接列表的文章指出: > 在计算机科学中,链表是数据元素的线性集合,其中线性顺序不是由它们在内存中的物理位置所给出的。相反,每个元素指向下一个元素。它是由一组节点组成的数据结构,它们共同代表一个序列。在最简单的形式下,每个节点都由数据和一个指向下个节点的引...阅读全文

博文 2018-03-25 23:02:44 SergeyChang

go内存管理和垃圾收集简介

go语言的内存分两部分,一部分用作堆,供内存分配用,另一部分是bitmap,用来管理堆。两部分从同一地址开始,向高地址方向增长的是内存池,向低地址方向增长的是bitmap。 ##内存分配## 对于较大的内存申请,直接从堆上申请,释放时也直接返回给堆。 而当一个go routine申请小于32k字节的内存,则从go routine私有的内存池中分配内存。因为是私有的,所有在多数情况下,分配内存不需要上锁。如果私有内存池没有内存了,则需要向中心内存池申请内存,中心内存池是共享数据,此时需要上锁。如果中心内存池也没有内存了,则从堆里申请内存。 私有内存池和中心内存池里的内存都是按照大小分开管理的,这样,分配和释放内存都非常快,而且也不容易产生碎片。通常,中心内存池从堆上申请...阅读全文

正确理解golang slice的复制

slice 三个属性 golang 的slice是一个指向底层的数组的指针结构体。 这个结构体有三个属性,1.指向数组指针,2.len: slice中元素的数量 3.cap:slice占用内存数量。 只有深刻理解这三个属性才能在使用slice中不至于犯错。 正确理解变量和共享 多个slice之间可以共享底层的数据,并且引用的数组部分区间可能重叠 以上是golang 圣经中的一句话。深刻理解这句话对于日程编程非常有意义。 1.什么时候共享数据会被其他变量修改 func f1() { a1 := []int{1,2,3,4,5,6} a2 := a1 a3 := a1[1:3] a1[1] = 999 fmt.Println("a1=",a1,"a2=",a2,"a3=",a3) } 运行结果 ...阅读全文

Golang笔记之值类型和引用类型

值类型:所有像int、float、bool和string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中。当使用等号=将一个变量的值赋给另一个变量时,如 j = i ,实际上是在内存中将 i 的值进行了拷贝。可以通过 &i 获取变量 i 的内存地址 引用类型:复杂的数据通常会需要使用多个字,这些数据一般使用引用类型保存。一个引用类型的变量r1存储的是r1的值所在的内存地址(数字),或内存地址中第一个字所在的位置,这个内存地址被称之为指针,这个指针实际上也被存在另外的某一个字中。 局部变量被声明后必须在相同的代码块中使用它,否则会得到编译错误,全局变量允许声明但不使用 如果要交换两个变量(已声明且赋值)的值,可以简单地使用a,b = b,a,这被称为并...阅读全文

博文 2017-05-17 12:23:47 弧度里的微笑

来,控制一下 Goroutine 的并发数量

文地址:来,控制一下 Goroutine 的并发数量 问题 func main() { userCount := math.MaxInt64 for i := 0; i < userCount; i++ { go func(i int) { // 做一些各种各样的业务逻辑处理 fmt.Printf("go func: %d\n", i) time.Sleep(time.Second) }(i) } } 在这里,假设 userCount 是一个外部传入的参数(不可预测,有可能值非常大),有人会全部丢进去循环。想着全部都并发 goroutine 去同时做某一件事。觉得这样子会效率会更高,对不对! 那么,你觉得这里有没有什么问题? 噩梦般的开始 当然,在特定场景下,问题可大了。因为在本文被丢进去同...阅读全文

Go 语言指针

Go 语言指针Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。接下来让我们来一步步学习 Go 语言指针。我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。以下实例演示了变量在内存中地址:package main import "fmt" func main() { var a int = 10 fmt.Printf("变量的地址: %x\n", &a ) }执行以上代码输出结果为:变量的地址: 20818a220现在我们已经了解了什么是内存地址和如何去反问它。接下来我们将具体介绍指针。什么是指针一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。类似于变量和常量,...阅读全文

博文 2016-01-31 05:00:01 u011225629

简约语言:golang; CSP式的并发模型

用python开发也有几年了,很喜欢它的简洁。最近在看golang,感觉和python很像,语法简洁,标准类型相识,标准库也是一样的丰富。引用一段文字(http://blog.csdn.net/myan/article/details/2028545): 所谓”魔幻语言“,主要代表作品有C++、Perl、Javascript和Ruby。这些语言拥有丰富的特性,聪明的技 巧和意想不到的奇效,永远有发掘不完的奇技淫巧,总能找到让人匪夷所思的”yet another way"。反过来,“简约语言”崇尚清晰直接,够用就行,要求从代码容易理解,宁可笨一点、累一点、多写一点代码,反对出人意料的技巧,反对故弄玄虚。 C、PHP、Python和Lua这一派语言的代表作。 看来golang也是“简约语言”。 ...阅读全文

博文 2014-10-04 19:27:17 seewind

Golang高阶:Golang协程实现原理

版权所有,转载请注明:http://www.lenggirl.com/go/goroutine.html 引言 实现并发编程有进程,线程,IO多路复用的方式。(并发和并行我们这里不区分,如果CPU是多核的,可能在多个核同时进行,我们叫并行,如果是单核,需要排队切换,我们叫并发) 进程是计算机资源分配的最小单位,进程是对处理器资源,虚拟内存(1)的抽象,而虚拟内存是对主存资源和文件(2)的抽象,文件是对I/O设备的抽象。线程是计算机调度的最小单位,共享同个进程分配的计算机资源。 上面这些是在深入理解计算机系统说的,如果有错来咬我呀。 总上所述,实际实现并发的是线程。首先,每个进程都有一个主线程,因为线程是调度的最小单位,你可以只有一个线程,但是你也可以创建多几个线程,线程调度需要CPU来切换,...阅读全文

博文 2019-05-15 11:34:56 veeeeeeeeeeee

golang中值类型/指针类型的变量区别总结

前言 值类型:所有像int、float、bool和string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中。当使用等号=将一个变量的值赋给另一个变量时,如 j = i ,实际上是在内存中将 i 的值进行了拷贝。可以通过 &i 获取变量 i 的内存地址 指针类型:简单地说go语言的指针类型和C/C++的指针类型用法是一样的,除了出去安全性的考虑,go语言增加了一些限制,包括如下几条: 不同类型的指针不能互相转化,例如*int, int32, 以及int64 任何普通指针类型*T和uintptr之间不能互相转化 指针变量不能进行运算, 比如C/C++里面的++, --运算 下面将给大家详细介绍golang中值类型/指针类型的变量的一些区别,下面话不多...阅读全文

博文 2017-12-11 21:00:01 yoyonow

golang map遍历

map 遍历 遍历的顺序是随机的 基本的遍历方式 func main() { m := map[string]int{ "a": 1, "b": 2, } for k, v := range m { fmt.Println(k, v) } } /* 可能的输出之一 a 1 b 2 */ /* 可能的输出之二 b 2 a 1 */ 遍历的时候元素的顺序是随机的,有可能先输出a,也有可能先输出b 在遍历中增加元素 在遍历的同时增加元素,增加的元素是可以被遍历到的 func main() { m := map[string]int{ "a": 1, "b": 2, } for k, v := range m { m["c"] = 3 fmt.Println(k, v) } } /* 输出 b 2 ...阅读全文

go中string和slice no-copy转换

在go里面,string和slice的互换是需要进行内存拷贝的,虽然在底层,它们都只是用 pointer + len来表示的一段内存。 通常,我们不会在意string和slice的转换带来的内存拷贝性能问题,但是总有些地方需要关注的,刚好在看vitess代码的时候,发现了一种很hack的做法,string和slice的转换只需要拷贝底层的指针,而不是内存拷贝。当然这样做的风险各位就要好好担当了: func String(b []byte) (s string) { pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b)) pstring := (*reflect.StringHeader)(unsafe.Pointer(&s)) pstring...阅读全文

博文 2015-06-18 09:09:35 siddontang

关于golang中的引用类型(reference type)

map,指针(pointers),还有slice,按照我的理解,这样的一个变量,存的就是个内存地址,而这样的一个声明 var a map[int]string var p *int var arr []string 在没有初始化之前都是nil,对这样的一个变量进行写(write)操作,都会抛出一个运行异常(a runtime panic),当然,append操作是可以的,或者用在声明的同时用make初始化一下也可以。 现在需要去验证的是,初始化的map或者slice是有一定默认空间的(尤其是map),如果不用append,直接a[x]=n来增加值,会不会越界抛出异常。。...阅读全文

博文 2016-06-13 14:00:02 hificamera

Go Runtime hashmap实现

前两天有小伙伴问道是否看过 Go 语言 map 的实现,当时还真没看过,于是就花了一点时间看了一遍 runtime 源码中的 hashmap 实现。map 的底层实现就是一个 hash 表,大体结构上和平时在脑海里的 hash 表差不多,但确实有很多细节(“Devils in the details”)。 hashmap 通过一个 bucket 数组实现,所有元素将被 hash 到数组中的 bucket 中,bucket 填满后,将通过一个 overflow 指针来扩展一个 bucket 出来形成链表,也就是解决冲突问题。这也就是一个基本的 hash 表结构,没什么新奇的东西,下面总结一些细节吧。 注意一个 bucket 并不是只能存储一个 key/value 对,而是可以存储8个 key/...阅读全文

深入理解 Go map:赋值和扩容迁移

概要 在 上一章节 中,数据结构小节里讲解了大量基础字段,可能你会疑惑需要 #&(!……#(!¥! 来干嘛?接下来我们一起简单了解一下基础概念。再开始研讨今天文章的重点内容。我相信这样你能更好的读懂这篇文章 原文地址:深入理解 Go map:赋值和扩容迁移 哈希函数 哈希函数,又称散列算法、散列函数。主要作用是通过特定算法将数据根据一定规则组合重新生成得到一个散列值 而在哈希表中,其生成的散列值常用于寻找其键映射到哪一个桶上。而一个好的哈希函数,应当尽量少的出现哈希冲突,以此保证操作哈希表的时间复杂度(但是哈希冲突在目前来讲,是无法避免的。我们需要 “解决” 它) 链地址法 在哈希操作中,相当核心的一个处理动作就是 “哈希冲突” 的解决。而在 Go map 中采用的就是 "链地址法 " 去解...阅读全文

博文 2019-03-24 21:34:40 煎鱼

c,golang 条件变量的使用对比

看到golang 标准库 sync package 提供了传统的mutex, once, cond, rwmutex 等基于共享内存的同步原语,就想写个代码实验一下。 type Cond struct { // L is held while observing or changing the condition L Locker // contains filtered or unexported fields } Cond 结构包含一个可导出的Locker 对象 func NewCond(l Locker) *Cond NewCond 函数 接受一个实现Locker 接口的对象, 返回一个指向Cond 的指针; pthread_cond_t 对应于此 func (c *Cond) Bro...阅读全文

博文 2015-01-15 14:00:01 yujian0231

指针与引用

点击上方蓝色“Golang来啦”关注我哟加个“星标”,天天 15 分钟,一起学 Go『就要学习 Go 语言』系列 -- 第 27 篇分享好文前几天,有同学在技术交流群里问:指针与引用的区别?在群里没做太多解释,回去找了篇 Steve Francia 大神关于「指针与引用」的文章,翻译过来了,可以点击文末的「阅读原文」查看原版。包括 C、C++ 在内的一些语言支持指针。其他语言包括 C++、Java、Python、Ruby、Perl 和 PHP 都支持引用。从表面上看,引用和指针非常相似,它们都用来让一个变量提供对另一个变量的访问。由于两者都提供了许多相同的功能,所以常常不清楚它们各自的内部机制有什么不同。在本文中,我将说明指针和引用之间的区别。为什么这很重要指针是 Go 语言的核心。大多数程...阅读全文

博文 2019-08-31 21:13:12 Golang来啦

Golang 1.3 sync.Atomic源码解析

上一篇文章我们说到sync.Mutex的源码实现,核心就是使用到了CPU指令CAS,从并发性能上来说atomic的效率是要高于mutex的,毕竟mutex做了不少的其他步骤,而atomic的核心其实就是和处理器密切关系的,通过一两个指令就能完成的原子操作,我们接下来来看看atomic在golang中的一些细节。 通过目录: 64bit_arm.go asm_amd64p32.s asm_linux_arm.s atomic_test.go race.go asm_386.s asm_arm.s asm_netbsd_arm.s doc.go asm_amd64.s asm_freebsd_arm.s atomic_linux_arm_test.go export_linux_arm_test...阅读全文

博文 2014-10-19 09:03:49 毛, 剑

golang 基础(5)函数的返回值

square-gopher.png 在 go 语言中函数支持多个返回值 func div(a, b int) (int, int){ return a /b , a %b } 我们也可以给函数返回值打上标签 q, r func div(a, b int) (q,r int){ return a /b , a %b } 我们可以用两个变量来接受函数返回值 a, b := div(17,3) 如果我们只想使用一个返回值,也就是 a 而不使用 b,向下面这样做会在编译时报错,go 语言是比较严格语言 strict-inspection.jpg a, b := div(17,3) fmt.Println(a) 应该修改为,通过 _ 占位符来忽略掉不使用的变量 a, _ := div(17,3) fm...阅读全文

程序员最想学习的语言竟然是:Go!

前面我们说过,目前使用人数最多的语言,依旧是Java语言,但是不知道各位读者可听说过Go语言呢?最近,汇集了超过 500 万开发人员(占全球开发人员总数的 20% 以上)的国外开发者平台 HackerRank 发布了一份技能报告,结果表明: 2019 年程序员最想学习的编程语言 Top 3 分别是 Go、Kotlin 和 Python,其中 Go 以 37.2% 的比例排在首位。 GO语言成为程序员最想学习的语言之一 今年也是 Go 语言发布 10 周年,2007 年 3 位 Google 天才程序员想通过开发一种新型的语言,解决 Google 软件开发中面临的问题:多核硬件架构、超大规模分布式计算集群、Web 开发模式导致的前所未有的开发规模和更新速度,于是 Go 语言诞生了。 这些问题,...阅读全文

博文 2019-04-01 13:35:10 Joker_影

Golang-TCP异步框架Tao分析

TCP异步框架 Golang 编程风格 Go语言面向对象编程的风格是多用组合,少用继承,以匿名嵌入的方式实现继承。 掌握Go语言,要把握一个中心,两个基本点。 一个中心是Go语言并发模型,即不要通过共享内存来通信,要通过通信来共享内存; 两个基本点是Go语言的并发模型的两大基石:channel和go-routine。 不要通过共享内存来通信,要通过通信来共享内存 这句话的大概解释是: 不要通过共享内存来实现通信,这是因为在复杂的分布式、多线程和多进程之间通过加锁等控制并发方式来保证数据的正确性,是非常困难和低效的。建议线程之间通过通道channel来实现通知,降低数据的竞争,提高系统的可靠性和正确性。 1. 服务启动开始 1.1 启动心跳定时器循环 func (s *Server) time...阅读全文

博文 2017-09-04 09:34:51 wiseAaron

Go的三色标记GC

三色标记 三色标记的原理如下:整个进程空间里申请每个对象占据的内存可以视为一个图, 初始状态下每个内存对象都是白色标记,先stop the world,将扫描任务作为多个并发的goroutine立即入队给调度器,进而被CPU处理,第一轮先扫描所有可达的内存对象,标记为灰色放入队列;第二轮可以恢复start the world,将第一步队列中的对象引用的对象置为灰色加入队列,一个对象引用的所有对象都置灰并加入队列后,这个对象才能置为黑色并从队列之中取出。循环往复,最后队列为空时,整个图剩下的白色内存空间即不可到达的对象,即没有被引用的对象; 第三轮再次stop the world,将第二轮过程中新增对象申请的内存进行标记(灰色),这里使用了writebarrier(写屏障)去记录这些内存的身份...阅读全文

go语言中var

go语言中定义变量使用关键字var,如:var x int=4 也可以写成x:=4; 在函数中,:= 简洁赋值语句在明确类型的地方,可以用于替代 var 定义。 (:= 结构不能使用在函数外,函数外的每个语法块都必须以关键字开始。) package main import ( "fmt" ) func main() { var x int = 4 fmt.Println(x)//输出4 fmt.Println(&x)//输出指针 //fmt.Println(*x) //错误 y := 4 fmt.Println(y)//输出4 fmt.Println(&y)//输出指针 //fmt.Println(*y) //错误 var v *int = new(int)//返回值为指针 fmt.Prin...阅读全文

修改golang最大内存限制

摘自golang nut You can tune the MHeapMap_Bits in malloc.h and arena_size in malloc.goc to reduce memory usage, as long as they statisfy this: (1UL << (12 + MHeapMap_Bits)) >= arena_size (for example, I changed MHeapMap_Bits to 20, and arena_size to ”4LL<<30“, all tests passed, and the size of bss sections is dropped to about 10MB for bin/go: linux-am...阅读全文

博文 2016-04-22 21:00:01 sorawa

Golang指针与nil浅析

曾经听说过一句话,编程的本质就是指针和递归。那会刚开始编码,只是这两个的概念有个感性粗浅的认识。最早接触指针,莫过于C语言了,能否理解用好指针也成为一个合格C语言的基本标志。 Golang也提供了指针,但是go不能进行指针运算,因此相对于C也少了很多复杂度。私以为,go之所以提供指针,并不是为了让你更多和内存打交道,而是提供操作数据的基本桥梁。因为go很多调用,往往复制一份对象,例如函数的参数,如果没有指针,有些情况不得不存在很多副本。 内存和变量 编程语言中一般都会有变量。变量存储一些值。通常我们会对变量声明,赋值,和销毁等操作。 想象一下,内存好比一个长长的桌子,桌子有很多连续的抽屉(内存块)。我们可以按照顺序给每一个抽屉从0开始编号(内存地址),这个编号就是抽屉的地址。当我们需要使用抽...阅读全文

博文 2017-07-22 10:06:37 人世间

[golang note] 协程通信

channel基本语法 • channel介绍 √ golang社区口号:不要通过共享内存来通信,而应该通过通信来共享内存。 √ golang提供一种基于消息机制而非共享内存的通信模型。消息机制认为每个并发单元都是自包含的独立个体,并且拥有自己的变量,但在不同并发单元间这些变量不共享。每个并发单元的输入和输出只有一种,那就是消息。 √ channel是golang在语言级提供的goroutine间的通信方式,可以使用channel在两个或多个goroutine之间传递消息。 √ channel是进程内的通信方式,如果需要跨进程通信,建议使用分布式的方法来解决,比如使用Socket或HTTP等通信协议。 √ channel是类型相关的,即一个channel只能传递一种类型的值,需要在声明cha...阅读全文

博文 2016-03-16 03:00:01 heartchord

Go语言数据结构

当向一个新程序员解释Go语言时,我发现如果解释Go的数据是如何在内存中表示的,将有助于建立编写高效程序的良好直觉。 转载地址:http://www.open-open.com/lib/view/open1390373069882.html 基础类型 让我们从一些简单的例子开始: 变量i是int类型,在内存中占用一个32位的存储单位。(上图拿32位系统来举例;对以上的例子,只有指针才会在64位的机器上占用更多的空间——int始终是32位——然而我们仍然可以选择64位的系统。) 变量j是int32类型,因为它经过了显式的类型转化。尽管i和j有着同样的内存布局,但它们的类型是不一样的:像这样的赋值i = j会产生类型异常,必须通过显式的类型转换:i = int(j) 。 变量f是个浮点类型,上例中...阅读全文

博文 2015-04-09 11:00:01 Decadent_2014

【深度知识】GO语言的goroutine并发原理和调度机制

1. 线程(Thread)和协程(Coroutine)的定义 Go语言最大的特色就是从语言层面支持并发(Goroutine),Goroutine是Go中最基本的执行单元。事实上每一个Go程序至少有一个Goroutine:主Goroutine。当程序启动时,它会自动创建。 为了更好理解Goroutine,现讲一下线程和协程的概念。 线程(Thread):有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆(heap, 一般由程序员分配释放)栈(stack,由编译器自动分配释放 ,存放函数的参数值,局部变量的值等)组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己...阅读全文

博文 2019-08-02 01:02:41 笔名辉哥

Go 语言的并发模型--通过通信来共享内存

载:http://se77en.cc/2014/04/08/share-by-communicating-the-concurrency-slogan-in-golang/ 概述 我一直在找一种好的方法来解释 go 语言的并发模型: 不要通过共享内存来通信,相反,应该通过通信来共享内存 但是没有发现一个好的解释来满足我下面的需求: 通过一个例子来说明最初的问题提供一个共享内存的解决方案提供一个通过通信的解决方案 这篇文章我就从这三个方面来做出解释。 读过这篇文章后你应该会了解通过通信来共享内存的模型,以及它和通过共享内存来通信的区别,你还将看到如何分别通过这两种模型来解决访问和修改共享资源的问题。 前提 设想一下我们要访问一个银行账号: 123456789101112131415161718...阅读全文

博文 2015-06-29 03:00:00 yugongpeng_blog