Go语言学习(3)-类型

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 main

import (
"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.")
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值