范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

go语言的基础组件

  go语言自带的基础类型包括int :有符号的整数类型,具体占几个字节要看操作系统的分配,不过至少分配给32位。uint:非负整数类型,具体占几个字节要看操作系统的分配,不过至少分配给32位。int8:有符号的整数类型,占8位bit,1个字节。范围从负的2的8次方到正的2的8次方减1。int16:有符号的整数类型,占16位bit,2个字节。范围从负的2的16次方到正的2的16次方减1。int32:有符号的整数类型,占32位bit,4个字节。范围从负的2的32次方到正的2的32次方减1。int64:有符号的整数类型,占64位bit,8个字节。范围从负的2的64次方到正的2的64次方减1。uint8:无符号的正整数类型,占8位,从0到2的9次方减1.也就是0到255.uint16:无符号的正整数类型,占16位,从0到2的8次方减1.uint32:无符号的正整数类型,占32位,从0到2的32次方减1.uint64:无符号的正整数类型,占64位,从0到2的64次方减1.uintptr:无符号的储存指针位置的类型。也就是所谓的地址类型。rune :等于int32,这里是经常指文字符。byte:等于uint8,这里专门指字节符string:字符串,通常是一个切片类型,数组内部使用runefloat32:浮点型,包括正负小数,IEEE-754 32位的集合float64:浮点型,包括正负小数,IEEE-754 64位的集合complex64,复数,实部和虚部是float32complex128,复数,实部和虚部都是float64error,错误类型,真实的类型是一个接口。bool,布尔类型
  int8 和uint8 后面的8指的是占得位数,因为有符号的第一位作为符号位置,所以它真的可以计数的位置只有7个了,第一位表示正负,无符号的整数显然没有这个烦恼。
  go语言的基础组件分为以下几种:
  其中按照是否是引用类型(指针类型)分为引用类型和非引用类型,他们分别是
  引用类型
  非引用类型
  slice,interface,chan,map
  array,func,struct,大部分的内置类型
  这里要说明以下,所有的非引用类型的初始化值都是一个具体的值,只有引用类型的初始化是nil,nil在go里面就是指的是空。是不能直接使用的。
  全局变量,引用类型的分配在堆上,值类型的分配在栈上。
  局部变量,一般分配在栈上。如果局部变量太大,则分配在堆上。如果函数执行完,仍然有外部引用此局部变量,则分配在堆上。
  我们分别来介绍以下他们。array
  数组,我们先看一下数组的初始化。// 给数组进行初始化  // 初始化的方式1 a := [6]string{}  // 初始化的方式2 var a [6]string
  这里稍微提一下,在go里面的赋值符号有两种:var a   b :=
  其中var 这种方式不论是局部还是全局变量都可以使用,但是后者也就是:=只有局部变量可以使用。也就是只有函数内部才能使用。
  并且,var后面的变量后面的类型是可以省略的,省略后,go会在编译过程中自动判断。所以如果不省略就是长这样.var a int
  说到了变量,go里面当然也有定量,使用const来命名,一般都是全局使用。// 根据习惯一般用大写表示定量 const PAI = 12
  同样的,定量也可以省略后面的类型。
  接下来我们看一下数组的赋值a[0] = "0" a[1] = "1" a[2] = "2" a[3] = "3" a[4] = "4" a[5] = "5"
  这里要点明一下,值类型,或则说非引用型类型的"声明" 就等于初始化,也就是说,当你给一个变量声明一个值类型的数据时,就自动给定了初始值。
  这里谈一下他们的初始值:
  array
  int
  string
  bool
  float
  func
  struct
  空数组,但不是nil,已经占用了声明的数组长度
  0
  空字符串,通常我们使用""代指空字符串   false   0
  就是一个空的函数   一个空的structure   length <4 的数组,数据是直接存在栈空间上的,如果数据大于4,那么会存放在静态空间,然后才复制到栈空间上,顺便说一下,堆和栈属于动态存储,其中栈是操作系统直接控制,我们的局部变量,不逃逸的情况下都是存在于栈中,逃逸了就去堆里面了,说完了动态,静态存储区域包含了两者,一个是存储的常量,一个是存储的静态变量,常量好理解就是const来声明的常量,静态变量,比如这里大于4的数组。   数组的语法糖[...]int 使用这种方式,必须在声明的时候直接赋值,否则下面进行赋值的时候,系统不知道你的length到底是多少,就会"out of index"   数组的初始化的中括号里要么是..., 要么就是个常量,不能是变量关于go里面的比较问题   只有类型一致的情况下,进行比较,比如struct int,等,接口也可以比较,slice map 以及函数体,都是无法进行比较的。chan 可以比较,但是即使是类型一样,也是false的结果,nil也是可以比较的,因为nil的底层是 var nil Type type Type int 也就是说nil其实是一个值类型。nil也是有类型的,比如说接口的nil就是接口类型,那么指针类型的nil就是指针类型,slice的nil就是这个slice类型。   一直在变的无法比较,一成不变的就可以比较,slice和map都因为底层指向可以一直变所以无法比较,函数体内部也是一直可以变,所以只有他们三个无法进行比较。slice   切片,是一个内置的引用类型,其实质是一个structure,也就是说是一个结构体,这个结构体内部含有一个指向某个数组的地址,所以说我们可以简单的来理解,slice是某个数组的指针。type SliceHeader struct { // 指向底层数组的指针类型 data uintptr // 长度 len int // 容量 cap int }   切片的初始化:a := make([]string,10) // 或者 var b [10]string a := &b // 或者 a := []string{1,2,3,} // 或者 a := [3]int{1,2,3,} // 左闭右开 b := a[0:2] x := b[0:1] // 等于c取了数组的全部数据 c := a[:]   这里涉及了几个知识点,首先是make()函数,这个函数是go的内置函数,意义就是为了给引用类型初始化,所以能使用make的就是这些引用类型,slice map chan,interface不可以使用,不好意思它make和new都不能使用。   new的含义就是说从一个值类型上取得它的地址,跟& 相似,后者是取地址的符号。并且new的括号里只能是Type类型。例如:type A map[string]string   切片会重新指向新的数组,比如当leng不够需要扩展,然后cap也不够的时候,就会创建一个新的数组底层,然后进行数据的迁移。   切片使用初始化的方式会在编译期间就完成了初始化,但是当使用make关键字创建的时候就会在运行时初始化,在运行时初始化会对速度造成影响。   当切片非常大,或者切片逃逸了,那么就会在堆上创建这个切片。   切片的扩容【考点】:func growslice(et *_type, old slice, cap int) slice { newcap := old.cap doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { if old.len < 1024 { newcap = doublecap } else { for 0 < newcap && newcap < cap { newcap += newcap / 4 } if newcap <= 0 { newcap = cap } } }   给定一个期望扩容数字:如果期望大于两倍的老容量,那么新的容量就是这个期待容量如果期望小于两倍的老容量,并且老的容量个数小于1024,那么新的容量就是老容量的二倍如果期望小于两倍的老容量,并且老的容量个数大于1024,那么这个容量就按照之前老容量的1.25倍开始增加,直到大于了期望容量,开始跳出循环如果老容量是小于等于0的,那么新的容量直接等于期望容量   当然这只是初步确定容量,下面还要进行内容的对齐。   切片的数据拷贝:copy(newSlice,oldSlice),这里直接是值的拷贝。谨防切片的数据入侵   谨防,两个切片共用一块公共内存的时候,发生数据的侵入,这个时候可以使用 限制容量 的方式来做到规避这个bug。package main import "fmt" func main() { A := []int{1, 2, 3, 4, 5, 6, 7} a := A[:3] b := A[3:] fmt.Println("第一次的a和b的数值", a, b) a = append(a, 21, 22) fmt.Println("第二次的a和b的值", a, b) fmt.Println("可以看出,因为a的append并没有超过cap所以说,a和b的底层内存是一块,b的数据被bug更改了") // 解决方法 B := []int{1, 2, 3, 4, 5, 6, 7} c := B[:3:4] // 这里的4就是一个限制容量参数。限制c的容量是4。 d := B[3:] fmt.Println("第一次c和d的值", c, d) c = append(c, 21, 22) fmt.Println("第二次测试c和d的值", c, d) fmt.Println(`这个时候发现,因为在给c定义slice的时候制定了限制的cap,也就是说c的cap被我人为的定义为了4" "所以c在append的时候就重新指向了一块新的内存地址`) }   c := B[:3:4] 这段代码是关键,这里的4就是一个限制容量参数。限制c的容量是4。map   map,也就是所谓的hash map 哈希表,散列表,在go里面的哈希表,使用的避免哈希碰撞的算法是链表法。map的key必须是Type,并且是可以比较的类型,例如int,string,interface{},bool,一般接口类型,不过不可比较的例如 slice map都无法充当key值。   我们来看一下map的初始化a := make(map[string]string)   make()后面其实是有三个值的,第一个就是类型,第二个是length长度,第三个是cap 容量,你先了解一下,slice是需要指定length值的,也就是第二个值,但是第三个并不需要指定,map更厉害,它只需要提供类型,后面两个都不需要提供。   禁止使用 var a map[string]string来初始化,这种只能是声明一个类型,因为声明后a变量的初始值是nil值,也就是说没有分配内存。   map的使用:a["0"] = "0" a["1"] = "1" a["2"] = "2" // 删除key delete(map,key) // ok表示是否含有这个值。 value,ok := a["1"]   说到length和cap,我们提一下len()和cap()函数。   这俩函数前者是可以测定array,slice,map的长度,后者是容量,说到长度和容量,听起来很相似,到底啥区别呢?   我们来举个例子:   上文我们谈到,slice的底层是一个数组,那么数组的整个的长度就是这个切片的容量,我们取前三个作为length,那么就是3就是这个slice的长度,所以长度<= 容量,再谈一个点,在go里面的所有关于slice是否 out of index 也就是说是否超过下标,指的都是长度而不是容量。func main(){ a := make([]string,10,20) a[10] ="1" }panic: runtime error: index out of range [10] with length 10   在map中,有两个数据非常关键,一个是hash function,一个是hash冲突   其中hash函数,分为两种,一种是加密型hash函数,例如rc4,sha,等,一种是非加密型函数,这种函数就是为了检索而生,例如murmur hash 函数。   hash冲突,简单的来说就是两个key使用hash函数计算出来的hash值是一样的,无法去定位真实的value值,那么我们有两种解决的方法,一种是向后寻找法,一种是链表法。   值得注意的是,这里的hash碰撞还不一定就是计算出来的hash值是完全一样,有可能是前某几位是一致的,因为我们取的可能是前几位,不可能取完,   向后寻找意思很简单,我们不论是查找的时候,或者是写的时候都是加入计算出的key,已经有人占据了,那么我们的数据就不放在这个坑了,我们往后找,看是不是有空缺的,如果有就放进去这个key-value数据。   这种方法特别要注意的是装载因子,因为hash表底层存储结构是数组,那么如果数组中的数/长度【这就是装载因子的意义】太大,那么向后寻找法就会很难找到数据,直至时间复杂度变成O(N)   链表法就是key计算出来的hash值一样的放在一个地方,只不过这个地方改成一个链表即可。然后我们查找的时候查找这个链表,看真正要找的key是具体哪个,然后我们取得这个key对应的value即可。这种方法要注意链表过长,过长的意思就是hash函数不行,造成分布不够均匀。或者函数生成的值过于狭窄。   map扩容的两个条件是,一是桶的装载因子超过6.5,二是当溢出桶中的元素数量过多的时候,也需要进行扩容了,如果不扩容就会降低map的性能,其中为了扩容时候的效率,在创建新的数据结构后,因为桶的数量改变了,会重新进行hash计算,并且把旧桶中数据进行分流到新的桶中。   在扩容期间访问哈希表时会使用旧桶,向哈希表写入数据时会触发旧桶元素的分流。   哈希表的每个桶都只能存储 8个键值对,一旦当前哈希的某个桶超出 8 个,新的键值对就会存储到哈希的溢出桶中。随着键值对数量的增加,溢出桶的数量和哈希的装载因子也会逐渐升高,超过一定范围就会触发扩容,扩容会将桶的数量翻倍,元素再分配的过程也是在调用写操作时增量进行的,不会造成性能的瞬时巨大抖动。func   函数,以及后文要谈的方法,都是这种形态。//1 func main(){ } //2 func fast(a string,b int)(float64,func (int,string)){ return 0,func()(int,string){ return 1, "" } } //3 func heigh(a int)(b string){ return "" } //4 var apple = func()(string){}   上面的函数显示了一个函数的基本样子,func关键字在最前面,后面是函数名称,函数后面的括号里是两个临时变量,再后面是返回的值,注意,如果返回的值只有一个,可以省略括号,并且go可以直接返回多值。   函数的使用:fast("",0)   调用的时候还是比较容易的。struct   结构体,我们来看一下基本的形态type A struct { v1 ,v2 int v3 bool }   使用type这个符号,加上变量名称,再加上一个struct,然后结构体内部的变量的声明就如同文中所示,一个变量,后面是类型,如果两个变量一致可以放一起。比如v1,v2,中间用,d   我们看一下结构体的使用// 这是声明,声明直接初始化。 var a A /* 下面是赋值 */ a.v1 = 1 a.v2 = 2 a.v3= true // 另一种赋值方式 var a = A { v1:1, v2:1, v3:true, // 这里注意一下,逗号一定要有,结尾处有逗号 } // 也可以省略前面的key,但是这样必须按照顺序 var a = A{ 1,3,true, } // 如果想取结构体的地址也是有两种方式的 var a = &A{ //xxx } // 另一种 var a = new(A)interface   go语言的接口,核心就是鸭子 理论,也就是说不像传统语言,java那种必须显示声明出来接口的调用,go语言中只需要实现接口的方法就是实现了这个接口。   声明一个接口type people interface { see() eat() }   内部的是函数,接口内部只接函数。   在此提示一下 接口与众不同,不可使用make和new来声明获取一个接口,接口并没有实际的任何意义,所以它没有任何的底层指向,使用make是没有意义的。同时因为interface的实质也是一个structure 只是内部是记录的一些参数,所以说取这个接口的地址也没有任何的意义,所以go里面不要取接口的地址。   如何实现这个接口?func c (p people){ p.see() p.eat() }   这里,这个函数的变量是接口类型,那么我们要传入的也应该是people这个接口类型,那么什么是符合这个接口类型呢?   等下文的面向对象再详细说一下。chan   chan,这里先简单介绍一下,后文go并发编程可以详细介绍一下。   因为chan也是引用类型,所以它也必须使用make才可以初始化c := make(chan string,2)   chan 后面要加上具体的类型,然后再加上长度即可。   这里你先简单的了解一下chan,中文叫做通道,你可以简单的和unix中的通道类比一下,后面的长度就是指的,通道内可以缓存的数据量,当然这里你把通道当作一个队列。   使用的时候可以这样做。func fast(){ c := make(chan string,2) go b(c) } func b(chan string){}   这里的go 关键字指的是开辟了一个新的goroutine,然后通道在不同的goroutine中流传传递信息。   其中,有两种特殊的命名方式,就是只读通道和只写通道。// 只读通道 var a <- chan string // 只写通道 var b chan <- string   往通道里读写数据这什么来操作的:// 写入数据 a <- "" // 读取数据 <- a   当然我们一般不会舍弃读取的通道数据,会将数据赋值给一个变量c := <- aiota   特殊常量,可以自增。切记,只能用在常量中。const ( a = 1+ iota b c d e f = "12" g= iota h i )   1 2 3 4 5 12 6 7 8 iota在常量中处于自增的方式,可以看到,iota的初始值是0,所以a等于1,b就是2,b等于1+1,当遇到f的时候,iota自己的自增没有变化,但是f就变了,变成了"12",然后g又给了iota,那么这个时候的iota就不是从零开始,iota的就是6,意思就是往下数嘛,从0开始,到g就是6了。又因为这个变量的赋值算式不是1+iota,是iota了,那么后面的就变成了直接将iota赋值给变量了。字符串   go语言中的字符串是一个只读字节切片,底层数组里存放的是byte类型,如果我们想改变这个字符串,可以将 字符串 <=> []byte 互相的转换,进而改变这个字符串,这个转化的过程,先将静态存储区的字符串转到栈或者堆中(数组较大就会转化到堆上)然后string转变为字节数组,更改数组中元素,再转为字符串即可。因为字符串作为只读的类型,我们并不会直接向字符串直接追加元素改变其本身的内存空间,所有在字符串上的写入操作都是通过拷贝实现的。   在两者进行数据转化的时候,是有性能的损失的,所以优化性能的话,可以选择减少字符串和[]byte之间的转换。func main() { a := "github.com/shgopher" b := []byte(a) b[0]= 12 fmt.Println(string(b)) }

无需跋涉雪域,在河北也能游西藏,这还有造价14000两的金顶想不想来一次朝圣之旅,无需远行西藏,更不用准备防晒霜和抗高原反应药,在河北就能望见布达拉。在河北省承德市有一座小布达拉宫,它是清朝乾隆皇帝庆为祝其六十大寿和皇太后八十寿辰,专门派人探访国际庄夜幕下的十里花廊犹如一片灯光海洋夜幕降临,华灯初上。走进位于河北省石家庄市鹿泉区的太平河景观带,绚丽多彩的灯光将沿河两岸装扮的美轮美奂,犹如置身于一片灯光的海洋里。除此之外,5公里长的河道两侧还栽种了上百种的鲜花探秘藏在太行山里的超级工程水库竟建在山顶上,太壮观7月23日,河北省石家庄市井陉县西南方向40公里处的张河湾水库,一片绿意盎然。在阳光的折射下,湖水就像碧绿的宝石,与连绵起伏的太行山勾勒出一幅美丽的山水画卷。无人机缓缓升起,俯瞰风太震撼!直击飞机低空飞行降落,感受擦头而过的刺激相信乘坐过飞机的人,都曾透过舷窗一览山河湖海的壮观美景。但有个难得一见的航空奇景,坐在飞机里的你肯定没见过。伴随着一阵急促的飞机轰鸣声,即将降落在跑道的飞机,与地面上的人们擦头而过520武汉3000余对新人领证,新人历经风雨牵手一生5。20谐音我爱你,成为近年来众多年轻人争相追捧的网络情人节。5月20日,全国各地迎来复工后的第一个领证高峰。当天一早,武汉市各大民政局婚姻登记处门前就排起了结婚登记的队伍。由于实天下第一奇松康熙曾派500御林军世代守护,枝头形如九条龙提及松树,相信很多人都会被它顽强的生命力和雄伟的树姿所折服。在位于河北省承德市丰宁满族自治县内,有一棵经历了六个朝代的古松,它枝繁叶茂,九个枝头延伸开来形如龙,造型称奇。据传,这棵你还在用单反和三脚架?太out了!看我是怎么用手机拍大片的我是一名雄安摄影师,2019年雄安新区进入5G时代,到处遍布着疾速的5G网络,而我与5G网相隔最远的距离就是一部自己看得上的手机。作为专业摄影师,专业单反设备一箩筐,为什么还要追求探访清代高考考场可容纳上百考生,还藏着一件小抄马甲7月7日,2020年高考将拉开帷幕,1071万名考生步入考场,迎来人生中不同寻常的一次大考。从古时的科举考试到如今的高考,都承载了每位莘莘学子求知的梦想。不管是科举还是高考,每个时探访国际庄的前世今生在这里,你可以一馆游遍石家庄最近,石家庄又新添了一处网红打卡地,它以极具现代化气息的造型建筑迷倒了众多人。在这里,你能感受到这座火车拉来的城市的历史底蕴,体验黑科技带来的刺激。这里就是位于正定新区的石家庄城市石家庄最大烂尾楼时隔6年后复工,粉刷后犹如童话世界11月3日,位于河北省石家庄市南二环南侧的祥云国际项目,黄绿色的城堡屋顶格外引人注目,建筑工人在屋顶正加紧施工,呈现出一派热火朝天的建设场面。祥云国际的复工,吸引了很多人前来拍摄,航拍石家庄共享电动车坟场,万辆单车摆在空地上,电池被取出现在,在石家庄市区各大街头,已经很难看到街兔共享电动车的身影,取而代之的便是刚刚上新的美团共享电动车。最近,在石家庄南二环附近的宋村西侧,密密麻麻的街兔共享电动车被停放在一片宽敞的
华为P40Pro重新上架华为商城,大家怎么看?相信大家也发现了,就是近几天华为商城又重新上架了p40pro,但是上架的版本是8128的,价格是5988元。其实我不太懂这次上架的意义是什么?大致回顾一下这款手机的亮点与不足吧这款苹果手机2022年04月09日新消息苹果手机苹果手机2022年04月09日新消息超清视话(VoNR)商用画质达720p无需功能费苹果iPhone手机苹果6和苹果8的区别库克态度强硬!有意见不要用iPhone网友安卓我小米12ultra外观敲定,处理器不是骁龙8,将与Mixfold2一起发布大家好,我是三月。上个月手机界出现了不少新成员,华为P50E,红米K50,荣耀magic4,realmeGTNeo3等,几款手机的表现都相当不错,尤其是K50和magic4。K50环形山设计再升级外加一体化流线机身,OPPOFindX5Pro再度出圈从OPPOFindX3系列开始,辨识度就成为了FindX系列产品线的侧重点之一。FindX3系列主打的环形山设计,形如月球上受陨石撞击而产生的环形山,看起来极具质感,对于颜狗来说,华为Mate50再曝光鸿蒙OS3全新骁龙8,花粉幸福来得太突然从增长期到饱和期,中国智能手机市场正在经历变革,整个行业也在波动中前行。整个行业进行发展,少不了各个手机厂商的努力,少不了高端手机厂商的支持。这不,国产手机厂商的龙头华为手机,现在只需三步解决卡顿!华为将为旧手机推出系统云翻新功能手机用的时间久了往往会出现卡顿问题,不少用户常常因此烦恼。近日,华为将为老旧手机推出系统云翻新功能,只需通过云备份数据恢复出厂设置云恢复数据,三步操作便可解决手机卡顿问题。众所周知华为路由器的配置与防火墙的配置总结一accesslist用于创建访问规则。(1)创建标准访问列表accesslistnormalspeciallistnumber1permitdenysourceaddrsourc震惊!淘宝宣布可以修改名称后,300万人连夜赶紧修改就在4月7日晚上,淘宝宣布可以修改账号名称之后,当天晚上,淘宝统计数据之后,竟然有300万人连夜修改名称!淘宝可以改账号名了看到这里,你是不是有点吃惊了!300万人连夜修改了淘宝名世界那么大,中国移动带你去看看5G到底能干什么?5G发布之初,小编没有多大的想象能力,只是觉得4G还没怎么用,5G怎么就来了相信很多人和小编一样,对5G的印象更多的是5G,而恰恰是这个解释了5G到底能干些什么也全国机动车保有量突破4亿辆4月7日,公安部公布统计数据显示,截至今年3月底,全国机动车保有量达4。02亿辆,其中汽车3。07亿辆,占机动车总量的76。37机动车驾驶人4。87亿人,其中汽车驾驶人4。50亿人换手机不如换手机壳,这届年轻人为啥不换机?中新财经4月9日电(记者吴涛)近日,包括中国信通院在内的多方数据显示,国内手机市场不振,出货量接连下滑,年轻人为什么不愿意换手机了还冲上微博热搜,引发讨论。这是因为啥?多款手机降价