-
通道(Channel)是Go语言中一种非常独特的数据结构。它可用于在不同Goroutine之间传递类型化的数据,并且是并发安全的。相比之下,其他类型都不是并发安全的。 Goroutine(也称为Go程序)可以被看做是承载可被并发执行的代码块的载体。 它们由Go语言的运行时系统调度,并依托操作系统线程(又称内核线程)来并发地执行其中的代码块。 通道类型仅由两部分组成,如:chan T 在这个类型字面量中,左边是代表通道类型的关键字chan,而右边则是一个可变的部分,即代表该通道类型允许传递的数据的类型(或称通道的元素类型)。这两部分之间需要以空格分隔。 与其它的数据类型不同,我们无法表示一个通道类型的值。因此,我们也无法用字面量来为通道类型的变量赋值。 我们只能通过调用内建函数make来达到目的。 make函数可接受两个参数。第一个参数是代表了将被初始化的值的类型的字面量(比如chan int),而第二个参数则是值的长度。 例如,初始化一个长度为5且元素类型为int的通道值,则需要这样写:make(chan int, 5) make函数也可以被用来初始化切片类型或字典类型的值。 通道值的长度应该被称为其缓存的尺寸,它代表着通道值中可以暂存的数据的个数。 注意,暂存在通道值中的数据是先进先出的,即:越早被放入(或称发送)到通道值的数据会越先被取出(或称接收)。 声明一个通道类型的变量,并为其赋值:ch1 := make(chan string, 5) 使用接收操作符<-向通道值发送数据,也可以使用它从通道值接收数据。 例如,向通道ch1发送字符串"value1",应该这样做:ch1 <- "value1" 从ch1那里接收字符串,则要这样:<- ch1 ,可以直接把接收到的字符串赋给一个变量,如:value := <- ch1 针对通道值的接收操作也可以有第二个结果值,如:value, ok := <- ch1 这样做的目的是为了消除与零值有关的歧义。这里的变量ok的值同样是bool类型的。它代表了通道值的状态,true代表通道值有效,而false则代表通道值已无效(或称已关闭)。 调用内建函数close来关闭通道值,就像这样:close(ch1) 通道类型属于引用类型。它的零值即为nil。查看全部
-
Go语言的字典(Map)类型其实是哈希表(Hash Table)的一个实现。 字典用于存储键-元素对(更通俗的说法是键-值对)的无序集合。 注意,同一个字典中的每个键都是唯一的。 字典类型的字面量如下: map[K]T 其中,“K”意为键的类型,而“T”则代表元素(或称值)的类型。 如果我们要描述一个键类型为int、值类型为string的字典类型的话,应该这样写:map[int]string 字典的键类型必须是可比较的,否则会引起错误。键类型不能是切片、字典或函数类型。 每个键值对的键和值之间由英文冒号分隔。以字典类型map[int]string为例,它的值的字面量可以是这样的: map[int]string{1: "a", 2: "b", 3: "c"} 我们可以把这个值赋给一个变量: mm := map[int]string{1: "a", 2: "b", 3: "c"} 然后运用索引表达式取出字典中的值,就像这样: b := mm[2] 也可以利用索引表达式来赋值,比如这样: mm[2] = b + "2" 这使得字典mm中与键2对应的值变为了"b2"。 现在我们再来向mm添加一个键值对: mm[4] = "" 之后,在从中取出与`4`和`5`对应的值: d := mm[4] e := mm[5] 此时,变量d和e的值都会是多少呢?答案是都为"",即空字符串。 但是mm[5]的求值结果为什么也是空字符串呢? 原因是,在Go语言中有这样一项规定,即:对于字典值来说, 如果其中不存在索引表达式欲取出的键值对,那么就以它的值类型的空值(或称默认值)作为该索引表达式的求值结果。由于字符串类型的空值为"",所以mm[5]的求值结果即为""。 Go语言为我们提供了另外一个写法,即: e, ok := mm[5] 针对字典的索引表达式可以有两个求值结果。第二个求值结果是bool类型的。 它用于表明字典值中是否存在指定的键值对。 在上例中,变量ok必为false。因为mm中不存在以5为键的键值对。 从字典中删除键值对的方法是调用内建函数delete,如: delete(mm, 4) 无论mm中是否存在以4为键的键值对,delete都会“无声”地执行完毕。“有则删除,无则不做”。 字典类型属于引用类型。它的零值即为nil。查看全部
-
package main import "fmt" func main() { //定义一个切片 var numbers4 = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} //为切片设置容量上界值为8 slice5 := numbers4[4:6:8] //4是元素下界索引,6是元素上界索引,8是容量上界值 length := (2) //5,6 长度 capacity := (4) //容量 5,6,7,8 fmt.Printf("切片slice5长度:%d\n", len(slice5)) fmt.Printf("切片slice5容量:%d\n", cap(slice5)) fmt.Printf("%v, %v\n", length == len(slice5), capacity == cap(slice5)) //将其长度延展得与其容量相同 slice5 = slice5[:cap(slice5)] //切片追加方法 slice5 = append(slice5, 11, 12, 13) //5,6,7,8,11,12,13 length = (7) fmt.Printf("%v\n", length == len(slice5)) for i := 0; i < len(slice5); i++ { fmt.Printf("切片的第%d个值是:%d\n", i, slice5[i]) } //定义一个切片 //slice5 := []int[5,6,7,8,11,12,13] slice6 := []int{0, 0, 0} //切片复制方法 把第二个参数值中的元素复制到第一个参数值中的相应位置上 copy(slice5, slice6) //0,0,0,8,11,12,13 e2 := (0) e3 := (8) e4 := (11) fmt.Printf("%v, %v, %v\n", e2 == slice5[2], e3 == slice5[3], e4 == slice5[4]) }查看全部
-
在进行“切片”操作的时候需要指定元素下界索引和元素上界索引,就像这样:numbers3[1:4] 在方括号中放入第三个正整数,如numbers3[1:4:4] 这第三个正整数被称为容量上界索引。 换句话说,它可以限制我们通过这个切片值对其底层数组中的更多元素的访问。 在上一节讲到的numbers3和slice1。针对它们的赋值语句是这样的: var numbers3 = [5]int{1, 2, 3, 4, 5} var slice1 = numbers3[1:4] 这时,变量slice1的值是[]int{2, 3, 4}。 但是我们可以通过如下操作将其长度延展得与其容量相同: slice1 = slice1[:cap(slice1)] 通过此操作,变量slice1的值变为了[]int{2, 3, 4, 5},且其长度和容量均为4。 现在,numbers3的值中的索引值在[1,5)范围内的元素都被体现在了slice1的值中。 这是以numbers3的值是slice1的值的底层数组为前提的。 如果我们在切片表达式中加入了第三个索引(即容量上界索引),如: var slice1 = numbers3[1:4:4] 那么在这之后,无论我们怎样做都无法通过slice1访问到numbers3的值中的第五个元素。 因为这超出了我们刚刚设定的slice1的容量。 这需要使用到内建函数append。append会对切片值进行扩展并返回一个新的切片值。 使用方法如下:slice1 = append(slice1, 6, 7) 通过上述操作,slice1的值变为了[]int{2, 3, 4, 6, 7}。 注意,一旦扩展操作超出了被操作的切片值的容量,那么该切片的底层数组就会被自动更换。 这也使得通过设定容量上界索引来对其底层数组进行访问控制的方法更加严谨了。 切片值的“复制”函数是调用copy函数。 该函数接受两个类型相同的切片值作为参数,并会把第二个参数值中的元素复制到第一个参数值中的相应位置(索引值相同)上。 这里有两点需要注意: 1. 这种复制遵循最小复制原则,即:被复制的元素的个数总是等于长度较短的那个参数值的长度。 2. 与append函数不同,copy函数会直接对其第一个参数值进行修改。查看全部
-
字符串的表示法有两种,即:原生表示法和解释型表示法。若用原生表示法,需用反引号“`”把字符序列包裹起来。若用解释型表示法,则需用双引号“"”包裹字符序列。 二者的区别是,前者表示的值是所见即所得的(除了回车符)。在那对反引号之间的内容就是该字符串值本身。而后者所表示的值中的转义符会起作用并在程序编译期间被转义。所以,如此表示的字符串值的实际值可能会与我们看到的表象不相同。 ------------解释型-表示法,是什么意思呢?查看全部
-
切片(Slice)与数组不同的是,无法通过切片类型来确定其值的长度。每个切片值都会将数组作为其底层数据结构。我们也把这样的数组称为切片的底层数组。 切片类型的字面量如:[]int 或[]string 不同长度的切片值是有可能属于同一个类型的。而不同长度的数组值必定属于不同类型。切片类型的声明:type MySlice []int 类型MySlice即为切片类型[]int的一个别名。切片值的表示:[]int{1, 2, 3} 我们在上一节讲到的操作数组值的方法同样适用于切片值。不过,还有一种操作数组值的方法我们没讲到。这种操作的名称就叫“切片”,如: var numbers3 = [5]int{1, 2, 3, 4, 5} var slice1 = numbers3[1:4] 切片表达式( 第二条赋值语句中在“=”右边部分)一般由(numbers3有三种可能)字符串、数组或切片的值以及由方括号包裹由英文冒号“:”分隔的两个正整数组成。这两个正整数分别表示元素下界和上界索引。在本例中,切片表达式numbers3[1:4]的求值结果为[]int{2, 3, 4}。可见,切片表达式的求值结果相当于以元素下界和上界索引作为依据从被操作对象上“切下”而形成的新值。被“切下”的部分不包含上界索引指向的元素。另外,切片表达式的求值结果会是切片类型的,且其元素类型与被“切片”的值的元素类型一致 我们也可以在一个切片值上实施切片操作。操作的方式与上述无异。如: var slice2 = slice1[1:3] slice2的值为[]int{3, 4}。注意,作为切片表达式求值结果的切片值的长度总是为元素上界索引与元素下界索引的差值len(slice2)即上例的3-1 除了长度,切片值以及数组值还有另外一个属性——容量。数组值的容量总是等于其长度。而切片值的容量则往往与其长度不同 一个切片值的容量即为它的第一个元素值在其底层数组中的索引值与该数组长度的差值的绝对值。获取数组、切片或通道类型的值的容量,我们可以使用内建函数cap,如: var capacity2 int = cap(slice2) 最后,要注意,切片类型属于引用类型。它的零值为nil,即空值。如果我们只声明一个切片类型的变量而不为它赋值,那么该变量的值将会是nil。例如: var slice3 []int 它的值是nil查看全部
-
Go语言-数组类型 一个数组(Array)就是一个可以容纳若干类型相同的元素的容器。这个容器的大小(即数组的长度)是固定的。比如,声明了一个数组类型:type MyNumbers [3]int 注:类型声明语句由关键字type、类型名称和类型字面量组成。 类型字面量用于表示某个类型的字面表示(或称标记方法)。用于表示某个类型的值的字面表示被称为值字面量或字面量。 类型字面量[3]int由两部分组成。第一部分是由方括号包裹的数组长度,即[3]。数组的长度是固定不变的。第二个组成部分是int表示数组可以容纳的元素类型。我们可以把MyNumbers当做数组类型[3]int来使用。 在表示一个数组类型的值时,应该把该类型的类型字面量写在最左边,然后用花括号包裹该值包含的若干元素。各元素之间以(英文半角)逗号分隔,即: [3]int{1, 2, 3} 把该数组字面量赋给一个名为numbers的变量:var numbers = [3]int{1, 2, 3} 注:这是一条变量声明语句。它在声明变量的同时为该变量赋值。 另一种方法是,可以省略类型字面量的长度,像这样: var numbers = [...]int{1, 2, 3} 使用索引表达式来访问该数组的任何一个元素,例如: numbers[0] // 会得到第一个元素 numbers[1] // 会得到第二个元素 注:索引表达式由字符串、数组、切片或字典类型的值(或者代表此类值的变量或常量)和由方括号包裹的索引值组成。在这里,索引值的有效范围是[0, 3)。对于数组来说,索引值既不能小于0也不能大于或等于数组值的长度。索引值的最小有效值总是0,而不是1。 要想修改数组值中的某一个元素值,可以使用赋值语句。例如要修改numbers中的第二个元素可以这样:numbers[1] = 4 获取数组长度的方法:len(数组名) var length = len(numbers) 注:len是Go语言的内建函数的名称。该函数用于获取字符串、数组、切片、字典或通道类型的值的长度。我们可以在Go语言源码文件中直接使用它。 如果只声明一个数组类型的变量而不为它赋值,那么需要指定这个数组的长度,数组的每个值将会使用默认值0表示。如: var numbers2 [5]int 则它的值会是 [5]int{0, 0, 0, 0, 0}查看全部
-
Go语言-字符串类型 一个字符串类型的值可以代表一个字符序列。这些字符必须是被Unicode编码规范支持的。从表象上来说是字符序列,但是在底层,一个字符串值却是由若干个字节来表现和存储的。 一个字符串(也可以说字符序列)会被Go语言用Unicode编码规范中的UTF-8编码格式编码为字节数组。 在一个字符串值或者一个字符串类型的变量之上应用Go语言的内置函数len将会得到代表它的那个字节数组的长度。这可能与我们看到的表象是不同的。 字符串的表示法有两种,即:原生表示法和解释型表示法。 若用原生表示法,需用反引号“`”把字符序列包裹起来。 若用解释型表示法,则需用双引号“"”包裹字符序列。 二者的区别是,前者表示的值是所见即所得的(除了回车符)。在那对反引号之间的内容就是该字符串值本身。而后者所表示的值中的转义符会起作用并在程序编译期间被转义。所以,如此表示的字符串值的实际值可能会与我们看到的表象不相同。 注意,字符串值是不可变的。一旦创建了一个字符串类型的值,就不可能再对它本身做任何修改。查看全部
-
byte与rune byte与rune类型有一个共性,即:它们都属于别名类型。byte是uint8的别名类型,而rune则是int32的别名类型。 byte类型的值需用8个比特位表示,其表示法与uint8类型无异。 一个rune类型的值即可表示一个Unicode字符。 Unicode是一个可以表示世界范围内的绝大部分字符的编码规范。关于它的详细信息,大家可以参看其官网(http://unicode.org/)上的文档,或在Google上搜索。 用于代表Unicode字符的编码值也被称为Unicode代码点。一个Unicode代码点通常由“U+”和一个以十六进制表示法表示的整数表示。例如,英文字母“A”的Unicode代码点为“U+0041”。 rune类型的值需要由单引号“'”包裹。例如,'A'或'郝'。这种表示方法一目了然。不过,我们还可以用另外几种形式表示rune类型值。 在rune类型值的表示中支持几种特殊的字符序列,即:转义符。它们由“\”和一个单个英文字符组成。查看全部
-
Go语言-复数类型 复数类型同样有两个,即complex64和complex128。存储这两个类型的值的空间分别需要8个字节和16个字节。 实际上,complex64类型的值会由两个float32类型的值分别表示复数的实数部分和虚数部分。而complex128类型的值会由两个float64类型的值分别表示复数的实数部分和虚数部分。 复数类型的值一般由浮点数表示的实数部分、加号“+”、浮点数表示的虚数部分,以及小写字母“i”组成。比如,3.7E+1 + 5.98E-2i。 正因为复数类型的值由两个浮点数类型值组成,所以其表示法的规则自然需遵从浮点数类型的值表示法的相关规则。查看全部
-
浮点数类型有两个,即float32和float64。存储这两个类型的值的空间分别需要4个字节和8个字节。 浮点数类型的值一般由整数部分、小数点“.”和小数部分组成。其中,整数部分和小数部分均由10进制表示法表示。另一种表示方法就是加入指数部分。指数部分由“E”或“e”以及一个带正负号的10进制数组成。 比如,3.7E-2表示浮点数0.037。又比如,3.7E+1表示浮点数37。 浮点数类型值的表示也可以被简化。比如,37.0可以被简化为37。又比如,0.037可以被简化为.037。 在Go语言里,浮点数的相关部分只能由10进制表示法表示,而不能由8进制表示法或16进制表示法表示。比如,03.7表示的一定是浮点数3.7。查看全部
-
输出时%X表示16进制,%d表示10进制 16进制: 它由0-9,A-F组成,字母不区分大小写 与10进制的对应关系是:0-9对应0-9;A-F对应10-15 N进制的数可以用0~(N-1)的数表示,超过9的用字母A-F 1.数值变量赋值,int类型默认是10进制表示, var num1 int = 10 (默认10进制) var num1 int = 010 (使用8进制表示,前缀是 0表示) var num1 int = 0xC (使用16进制表示,前缀是0x)查看全部
-
Go语言的整数类型一共有10个。 其中计算架构相关的整数类型有两个,即:有符号的整数类型int和无符号的整数类型uint。 size:=是赋值,专用术语叫“短变量声明”。这种声明并赋值的方式会省略关键字“var”和被赋值的变量的类型,这也是“短”的由来。 一个字节等于8bit查看全部
-
go语言使用var关键字定义变量,使用const关键字定义常量。 赋值 1、var num1 int = 1 2、var num1,num2 int = 1,2 3、var {num2 int = 4 num1 int =6 num3 int =7} 4、var {num1 int num2 int num3 int} num1,num2,num3 = 1,2,3查看全部
-
工作区是放置Go源码文件的目录;一般情况下,Go源码文件都需要存放到工作区中;但是对于命令源码文件来说,这不是必须的。 每一个工作区的结构都类似下图所示:/home/hypermind/golib: src/ pkg/ bin/ src目录用于存放源码文件;以代码包为组织形式 pkg目录用于存放归档文件(名称以.a为后缀的文件) 所有归档文件都会被存放到该目录下的平台相关目录中,用样以代码包为组织形式 平台相关目录:两个隐含的Go语言环境变量:GOOS(操作系统)和GOARCH(计算机架构)。以$GOOS_$GOPATH为命名方式,如:linux_amd64 <工作区目录>/pkg/<平台相关目录>/<一级代码包>/<二级代码包>/<末级代码包>.a bin目录:用于存放当前工作区中的Go程序的可执行文件 1.当环境变量GOBIN已有效设置时,该目录会变的无意义;当GOPATH的值中包含多个工作区的路径时,必须设置GOBIN,否则无法成功安装Go程序的可执行文件查看全部
举报
0/150
提交
取消