首页 > 学院 > 开发设计 > 正文

Go语言学习(3)-类型

2019-11-10 20:31:17
字体:
来源:转载
供稿:网友

Go语言内置的基础类型:

布尔类型:bool; 整型:int8、byte、int16、int、uint、uintptr等; 浮点类型:float32、float64; 复数类型:complex64、complex128; 字符串:string; 字符类型:rune; 错误类型:error; 此外,Go语言也支持以下这些复合类型: 指针(pointer) 数组(array) 切片(slice) 字典(map) 通道(chan) 结构体(struct) 接口(interface)

1、布尔类型

var v1 bool v1 = true v2 := (1 == 2) // v2也会被推导为bool类型 布尔类型不能接受其他类型的赋值,不支持自动或者强制的类型转化。 以下会导致编译出错 var b bool b = 1

2、整型

类 型 长度 (字节) 值 范 围 int8 1 128 ~ 127 uint8(即byte) 1 0 ~ 255 int16 2 -32768 ~ 32767 uint16 2 0 ~ 65535 int32 4 -2147483648 ~ 2 147483647 uint32 4 0 ~ 4294967295 int64 8 -9223372036854 775808 ~ 9223 372036854 uint64 8 0 ~ 18446744073 709551615 int 平台相关(32位机器上同int32,64位机器同int64) 平台相关(32位机器上同int32,64位机器同int64) uint 平台相关 平台相关 uintptr 同指针在32位平台下为4字节,64位平台下为8字节

常规开发中使用int或者uint即可

需要注意的是: int和int32在Go语言里被认为是两种不同的类型,编译器也不会帮你自动做类型转换,比如以下的例子会编译错误 var value2 int32 value1 := 64 //value1将会被自动推导为int类型 value2 = value1 //编译错误,由于类型不一致 可以自己做强制转换 value2 = (int32)value1

3、浮点型

Go语言定义了两个类型float32和float64,其中float32等价于C语言的float类型,float64等价于C语言的double类型 fvalue2:=12.0 其类型将被自动设为float64,若是不加小数点,则自动推导为int类型 若是用==来判断两个浮点数是否相等,可能会导致不稳定的结果

4、复数类型

复数实际上由两个实数构成,一个表示实部real,一个表示虚部imag 复数的表示 var value1 complex64 value1 = 3.2+12i value2 := 3.2+12i //value2是complex128类型 value3 := complex(3.2,12) 对于一个复数z=complex(x,y),就可以通过Go语言的内置函数real(z)获取该复数的实部,也就是x,通过imag(z)获取该复数的虚部,也就是y

5、字符串

Go语言中字符串的声明和初始化举例如下

func main(){ var str string str="hello world" ch:=str[0] fmt.PRintf("The length of /"%s/" is %d /n", str, len(str)) fmt.Printf("The first character of /"%s/" is %c./n", str, ch)}

//执行结果 The length of “hello world” is 11 The first character of “hello world” is h. 字符串的内容可以用类似于数组下标的方式获取,但是与数组不同,字符串的内容不能在初始化之后被修改 如上述 str[0]=’x’ 会出现编译错误 len(str) Go语言内置函数,用于获取字符串长度

6、字符类型

在Go语言中支持两个字符类型,一个是byte(实际上是unit8的别名)代表UTF-8字符串的单个字节的值;另一个是rune,代表单个unicode字符。

7、数组

一些常规的数组声明方法:

func main(){ var arr [32]byte //定义了一个长度为32的byte类型数组 arr[0]=1 fmt.Print(arr) fmt.Print(len(arr)) var arr2 [2]struct { x, y int32 } //复杂类型数组 fmt.Print(arr2) var arr3 [1000]*float64 //指针类型数组 [3][5]int // 二维数组 --表示三行五列的二维数组 //可以用Go语言的内置函数len()来获取。下面是一个获取数组arr元素个数的写法: arrLength := len(arr)}

元素访问

for i:=0;i<len(arr);i++{ fmt.Print(arr[i]) }

j:表示角标,v表示值。若是只需要用到其中一个,另一个可用匿名函数代替

for j,v :=range arr{ fmt.Println("arr element[", j, "]=", v) }

值类型 需要特别注意的是,在Go语言中数组是一个值类型,所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作。如果将数组作为函数的参数类型,则在函数调用时该参数将发生数据复制。因此,在函数体中无法修改传入的数组内容,因为函数内操作的只是传入数组的一个副本; 如下示例:

func main(){ array := [5]int{1,2,3,4,5} // 定义并初始化一个数组 modify(array) // 传递给一个函数,并试图在函数体内修改这个数组内容 fmt.Println("In main(), array values:", array)}func modify(array [5]int) { array[0] = 10 // 试图修改数组的第一个元素 fmt.Println("In modify(), array values:", array)}

执行结果: In modify(), array values: [10 2 3 4 5] In main(), array values: [1 2 3 4 5]

8、切片数组

上述所知数组的特点:数组的长度在定义之后无法再次修改;数组是指类型,每次传递都将产生一份副本。显然这种数据结构是无法满足开发者的真正需求。 不用失望,Go语言提供了数组切片(slice)这个非常酷的功能来弥补数组的不足。 初看起来,数组切片就像是一个指向数组的指针,实际上它拥有自己的数据结构,而不仅仅是一个指针。数组切片的数据结构可以抽象为以下3个变量: 1、一个指向原生数组的指针; 2、数组切片中的元素个数; 3、数组切片已分配的存储空间;

创建数组切片: 创建数组切片的方法主要有两种-基于数组和直接创建; 基于数组方法示例:

func main(){ // 先定义一个数组 var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // 基于数组创建一个数组切片 var mySlice []int = myArray[:5]//前五个元素创建切片数组 var mySlice2 []int = myArray[5:]//后五个元素创建切片数组 fmt.Println("Elements of myArray: ") for _, v := range myArray { fmt.Print(v, " ") } fmt.Println("/nElements of mySlice: ") for _, v := range mySlice { fmt.Print(v, " ") } fmt.Println("/nElements of mySlice2: ") for _, v := range mySlice2 { fmt.Print(v, " ") } fmt.Println()}

Go语言支持用myArray[first:last]这样的方式来基于数组生成一个数组切片,下标包含first不包含last,类似subString方法 直接创建示例: Go语言提供的内置函数make()可以用于灵活地创建数组切片。

func main(){ //创建一个初始元素个数为5的数组切片,元素初始值为0: mySlice1 := make([]int, 5) //创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间: mySlice2 := make([]int, 5, 10) //直接创建并初始化包含5个元素的数组切片: mySlice3 := []int{1, 2, 3, 4, 5} for _,v:=range mySlice1{ fmt.Print(v) } for _,v:=range mySlice2{ fmt.Print(v) } for _,v:=range mySlice3{ fmt.Print(v) }}

元素遍历同普通数组 动态增减元素: 数组切片支持Go语言内置的cap()函数和len()函数,其中cap()函数返回的是数组切片分配的空间大小,而len()函数返回的是数组切片中当前所存储的元素个数。 如果需要往上例中mySlice已包含的5个元素后面继续新增元素,可以使用append()函数。 如:mySlice = append(mySlice,1,2,3) 函数append()的第二个参数是一个不定参数,我们可以按照我们的需求添加,甚至直接将一个数组切片追加到另一个数组切片的末尾。 如:mySlice = append(mySlice,mySlice2…) 我们在第二个参数mySlice2后面加了三个点,如果省略的话,会有编译错误。因为mySlice中的元素类型是int,所以直接传递mySlice2是行不通的。加上省略号相当于把mySlice2包含的所有元素打散后传入。 基于数组切片后创建数组切片 oldSlice := []int{1, 2, 3, 4, 5} newSlice := oldSlice[:3] // 基于oldSlice的前3个元素构建新数组切片 有意思的是,选择的oldSlicef元素范围甚至可以超过所包含的元素个数,比如newSlice可以基于oldSlice的前6个元素创建,虽然oldSlice只包含5个元素。只要这个选择的范围不超过oldSlice存储能力(即cap()返回的值),那么这个创建程序就是合法的。newSlice中超出 oldSlice元素的部分都会填上0。 内容复制 数组切片支持Go语言的另一个内置函数copy(),用于将内容从一个数组切片复制到另一个数组切片。如果将入的两个数组切片不一样大,会按照较小的那个数组切片的元素个数进行复制。 slice1 := []int{1, 2, 3, 4, 5} slice2 := []int{5, 4, 3} copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中 copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置

9、Map

变量声明: 如:var myMap map[string] PersonInfo 声明一个map,key是string类型,value是PersonInfo类型

创建: 我们可以使用Go语言的内置函数make()来创建一个新map。下面的这个例子创建了一个key类型为string、值类型为PersonInfo的map: myMap = make(map[string] PersonInfo) 也可以创建一个初始存储能力为100的map: 如:myMap = make(map[string] PersonInfo,100) 创建并初始化: myMap = map[string] PersonInfo{ “1234”: PersonInfo{“1”, “Jack”, “Room 101,…”}, }

元素赋值: myMap[“test”] = PersonInfo{“1”, “Jack”, “Room 101,…”}

元素删除: delete(myMap, “test”)

元素查找: value, ok := myMap[“test”] if ok { // 找到了 // 处理找到的value } 判断是否成功找到特定的键,不需要检查渠道的值是否为nil,只需要查看第二个返回值ok。 示例:

package mainimport ("fmt")type PersonInfo struct { ID string Name string Address string}func main(){ var personDB map[string] PersonInfo personDB = make(map[string] PersonInfo) // 往这个map里插入几条数据 personDB["test"] = PersonInfo{"12345", "Tom", "Room 203,..."} personDB["test1"] = PersonInfo{"1", "Jack", "Room 101,..."} // 从这个map查找键为"1234"的信息 person, ok := personDB["test"] // ok是一个返回的bool型,返回true表示找到了对应的数据 if ok { fmt.Println("Found person", person.Name, "with ID test.") } else { fmt.Println("Did not find person with ID test.") }}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表