跳转至

数据类型


Go 是一种强类型语言。
每个变量都绑定到特定的数据类型,并且只接受与此类型匹配的值。

数据类型

类型
基本类型 数字、字符串和布尔值
聚合类型 数组和结构
引用类型 指针、切片、哈希、函数和管道
接口类型 接口

数值类型

基本类型

类型 说明(位是bit)
int 有符号整数,为32位或64位,由编译器决定
uint 无符号整数,为32位或64位,由编译器决定
int8 8位有符号整数
int16 16位有符号整数
int32 32位有符号整数
int64 64位有符号整数
uint8 8位无符号整数
uint16 16位无符号整数
uint32 32位无符号整数
uint64 64位无符号整数
rune int32 数据类型的别名。 它用于表示 Unicode 字符(或 Unicode 码位)
uintptr 无符号int指针类型
float32 浮点数
float64 浮点数
complex128 复数
complex64 复数
bool 布尔类型
byte 字节类型,同uint8
string 字符串类型
error 错误类型

bool类型

布尔类型值为truefalse
不支持自动或者强制类型转换

类型转换

不同类型之间不支持运算
显式声明类型转换

Go
1
2
var test int32 = 1
var test2 uint32 = (uint32)test

类型声明

type new_type old_type

Go
1
type INT int
new_type和old_type 底层相同,但仍是不同的类型

字符类型

byte: 代表UTF8字符串的单个字节的值
rune: 代表unicode字符

指针

指针的值是一个变量的地址

变量生命周期

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var p *int
fun f() {
    var x int = 1
    p = &x
}
//由于p指向局部变量x,x将从堆申请内存

fun g() {
    y := new(int)
    *y = 1
}
//由于y指向的地址只在函数内使用,当函数结束时,该内存将被自动释放

字符串

字符串是不可变字节序列,初始化后不能被修改
文本字符串被解读成安UTF-8编码的Unicode字符
每个元素为uint8类型

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main
import "fmt"

func main() {
    test := "123"
    test1 := "测试"
    fmt.Println(len(test), len(test1))

    test2 := test[:1] //创建新的字符串
    test3 := test + test1 //字符串拼接,产生新的字符串
}
//每个汉字占3个字节
//输出: 3 6

扩容

定义新的字符串

遍历

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var str = "it is test"

//根据长度遍历
strLen := len(str)
for i:=0; i<strLen; i++ {
    fmt.PrintLn(str[i])
}

//range
for i,v := range str { //注意range返回值为int32类型
    fmt.PrintLn(i,v)
}

处理包

  • bytes
  • strings
  • strconv
  • unicode

数组

数组是一种特定类型且长度固定的数据结构

  • 可以有零个或多个元素
  • 必须在声明或初始化时指定大小
  • 无法动态调整大小
  • 通过下标访问,从0开始到len-1
  • 根据类型默认初始化,或者指定赋值

鉴于这些原因,数组在 Go 程序中并不常用,但它们是切片和映射的基础。

声明

Go
1
2
3
4
5
6
//int类型数组,该数组有3个元素
var a [3]int
//string类型数组,该数组有3个元素
var b [3]string
//初始化多维数组
var twoD [3][5]int

初始化

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
//申请全局变量
var cities [5]string = [5]string{"New York", "Paris", "Berlin", "Madrid"}

//函数内局部变量
cities := [5]string{"New York", "Paris", "Berlin", "Madrid"}

//如果不知道需要多少个位置,但知道具有多少数据,那么使用省略号 (...),如下例所示:
q := [...]int{1, 2, 3}
//注意:=只能在函数内使用

//特定位置赋初值
numbers := [...]int{99: -1}

值类型

数组是值类型,在赋值或作为参数传递时,将被复制

切片

var name []Type
切片只是基础数组的一个视图
切片的大小是动态的,不是固定的

属性

  • 指针,指向原生数组的指针
  • 长度,切片内元素的个数。使用len()计算当前切片长度
  • 容量,切片存储空间大小。使用cap()计算容量。
  • 无法动态扩容,只能创建新切片(append时会自动扩容)

空切片

通过len判断数组是否为空

Go
1
2
3
4
var s []int     //len(s)==0 s==nil
s = nil         //len(s)==0 s==nil
s = []int(nil)  //len(s)==0 s==nil
s = []int{}     //len(s)==0 s!=nil

创建

  • 基于数组创建切片
  • 基于切片创建切片
  • 使用make()创建
    Go
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //该切片的长度len和cap均为0
    var slice0 []string 
    
    //基于数组创建切片 len:2 cap:12
    months := [...]string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
    slice1 := months[0:1] 
    
    //使用make创建切片,len:10 
    slice2 := make([]string, 10, 100) cap:100
    

访问

切片运算符 s[i]

追加元素

内置函数 slice = append(slice, element)向切片添加元素
当切片长度不够时,会自动分配新的切片

删除

无内置删除函数
通过创建新切片删除

Go
1
2
3
 letters := []string{"A", "B", "C", "D", "E"}
 remove := 2
 letters = append(letters[:remove], letters[remove+1:]...)

切片拷贝

copy(dst, src []Type)

map

哈希表

格式

Go
1
var hmap map[key]value

初始化

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    studentsAge := map[string]int{
        "john": 32,
        "bob":  31,
    }

    t := map[int]int{} //创建空map

    var studentsAge = make(map[string]int)

    //注意
    var studentsAge map[string]int
    //该方式定了一个nil,不能直接访问

添加

Go
1
2
3
4
5
    studentsAge := make(map[string]int) //正确定义
  ,后续赋值将出错
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println(studentsAge)

查找

Go
1
2
3
4
value, ok := map_test["123"]
if ok {
    do something...
}

访问项

下标表示法 map[key]

Go
1
2
3
4
5
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println("Bob's age is", studentsAge["bob"])
}

遍历

Go
1
2
3
4
5
6
7
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31

for name, age := range studentsAge {
    fmt.Printf("%s\t%d\n", name, age)
}

删除

内置函数delete()删除

Go
1
2
3
4
5
6
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    delete(studentsAge, "john")
    fmt.Println(studentsAge)
}

结构体

结构体可包含零个或多个任意类型的字段,并将它们表示为单个实体。

声明和初始化

使用 struct 关键字声明结构

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 例如,若要定义员工结构
type Employee struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

//然使用新类型声明一个变量
var john Employee
//声明变量的同时对其进行初始化
employee := Employee{1001, "John", "Doe", "Doe's Street"}
//指定字段赋值
employee := Employee{LastName: "Doe", FirstName: "John"}

//通过.访问
employee.ID = 1001
fmt.Println(employee.FirstName)

成员定义

通常将结构体成员首字母大写
便于夸包引用

结构嵌入

通过 Go 中的结构,可将某结构嵌入到另一结构中

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
//一种针对员工,一种针对合同工   
//你可具有一个包含公共字段的 Person 结构,如下例所示:
//公共字段
type Person struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}
//Employee
type Employee struct {
    Information Person
    ManagerID   int
}

匿名嵌套

定义只包含类型,不带名称的结构体成员

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type Person struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}
//Contractor
type Employee struct {
    Person  //匿名嵌套
    ManagerID int
}

Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main
import "fmt"

type Person struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

type Employee struct {
    Person
    ManagerID int
}

type Contractor struct {
    Person
    CompanyID int
}

func main() {
    employee := Employee{
        Person: Person{
            FirstName: "John",
        },
    }
    employee.LastName = "Doe"
    fmt.Println(employee.FirstName)
}