Golang 基础 - 数据类型

基本数据类型

intbyteint8int16runeint32int64uintuint8uint16uint32uintfloat32float64runeerrorstringbool

fmt.Printf 的一些常用占位符

%T%d%b%s%t%p%f%e

整型、浮点型

除了 byte 表示 int8 、rune 表示 int32 以及 ++ 和 – 只能单独存在外,其它的不用多说了,上示例:

import (
	"fmt"
)

func main() {
    var num_byte byte = 1
	var num_int8 int8 = 1
	var num_rune rune = 1
	var num_int32 int32 = 1
	// num_byte = int8, num_int8 = int8, num_rune = int32, num_int32 = int32
	fmt.Printf("num_byte = %T, num_int8 = %T, num_rune = %T, num_int32 = %T\n", num_byte, num_int8, num_rune, num_int32)

	// Golang 有加(+)减(-)乘(*)除(/)取余(%)自加(++)自减(--) 7 种算数运行符
	var numA int32 = 2
	numA++ // Golang 中 ++numA 为错误语法
	fmt.Println(numA) // 3
	numA-- // Golang 中 --numA 为错误语法
	fmt.Println(numA) // 2
}

字符串、字符

Golang 的字符串是不可变的,上示例:

import (
	"fmt"
)

func main() {
	// Go 语言的字符串使用双引号("")或者反引号(``)
	str := "ABCDE"
	// str = (string, ABCDE)
	fmt.Printf("str = (%T, %s)\n", str, str)

	strA := "A"
	charA := 'A'
	// Golang 的字符类型(rune)就是32位整型(int32)
	// strA = (string, A), charA = (int32, A)
	fmt.Printf("strA = (%T, %s), charA = (%T, %c)\n", strA, strA, charA, charA)

	// Golang 的语言使用 UFT-8 编码,中文占 3 个字节
	zhStr := "你好,世界"
	// 因为中文占 3 个字节,所以使用 len 方法将输出 13
	// zhStr = (string, 13)
	fmt.Printf("zhStr = (%T, %d)\n", zhStr, len(zhStr))
	// 使用 unicode/utf8 包提供的 RuneCountInString 方法获取字符的数目
	// zhStr = (string, 5)
	fmt.Printf("zhStr = (%T, %d)\n", zhStr, utf8.RuneCountInString(zhStr))
	// 或者使用 rune 类型处理(数据类型的转换)
	// zhStr = (string, 5)
	fmt.Printf("zhStr = (%T, %d)\n", zhStr, len([]rune(zhStr)))
}

布尔型

truefalse
import (
	"fmt"
)

func main() {
	fmt.Println(true && true, true)
    fmt.Println(true && false, false)
    fmt.Println(false && true, false)
    fmt.Println(false && false, false)
    fmt.Println(true || true, true)
    fmt.Println(true || false, true)
    fmt.Println(false || true, true)
    fmt.Println(false || false, false)
    fmt.Println(!true, false)
    fmt.Println(!false, true)
}

错误

error
type error interface {
    Error() string
}

示例:

import (
	"fmt",
    "errors"
)

func main() {
    fmt.Println(errors.New("Hello Error")) // Hello Error
}

复合数据类型

类型说明
array数组
slice切片
map字典
function函数
interface接口
channel通道
pointer指针

数组

[]
var 变量名 [长度]数据类型

示例:

import (
	"fmt"
)

func main() {
    // 声明一个长度为 5 的数组
    var arrayA [5]int
    // 数组会使用默认值进行填充,使用索引进行访问和修改
    arrayA[3] = 1
    // 也可以在声明时一同进行初始化
    arrayB := [5]int{1,2,3} // 1,2,3,0,0
    // 或者使用指定索引
    arrayC := [5]int{1:1,3:2} // 0,1,0,2,0
    // 使用 ...代替长度会自动填充长度
	arrayD := [...]int{1,2,3,4} // 长度为4
    arrayE := [...]int{2:1,6:2} // 长度为 7
}

遍历数组:

import (
	"fmt"
)

func main() {
    array := [...]int{1,2,3,4,5}
    
    // 使用 fori 循环遍历
    for i := 0; i < len(array); i++ {
        fmt.Printf("array[%d] = %d\n", i, array[i])
    }
    
    for index, value := range array {
        fmt.Printf("array[%d] = %d\n", index, value)
    }
}

多维数组和其它语言类似

import (
    "fmt"
)

func main() {
    array := [][]int{{1,2,3},{4,5,6},{7,8,9}}
    for _, arr := range array {
        for _, value := range arr {
            fmt.Printf("%d ", value)
        } 
		fmt.Println()
    }
}

切片

slice
var 切片名 []数据类型
lencapmakemake([]数据类型, 长度[,容量])
append
slice = append(slice, [元素]...)
import (
	"fmt"
)

func main() {
	var slice1 []int
    var slice2 []int
    slice2 = append(slice1, 1, 2, 3)
    fmt.Println(slice1) // []
    fmt.Println(slice2) // [1,2,3]
}

Golang 没有提供具体的删除切片元素的方法,一般通过使用获取切片片段来代替删除,示例

func main() {
	slice := []int{1,2,3,4}
	slice = slice[:] // slice = [1,2,3,4]
	slice = slice[1:] // slice = [2,3,4]
	slice = slice[:2] // slice = [2,3]
	// slice 的地址会发生改变
}

字典(map)

Golang 的 map 是无序的,不能通过下标获取,只能通过 key 访问对应的值

import (
	"fmt"
)

func main() {
    var map1 map[string]int // 声明一个key类型为字符串,value类型为int的map,没有初始化化,map1 为 nil
    map2 := make(map[string]int) // 声明并创建一个key类型为字符串,value类型为int的map,没有初始化化,map2 不为 nil
    map3 := map[string]int{"WenFlower": 99, "Wen": 60, "Flower": 59} // 声明并初始化map
    
    fmt.Println(map1 == nil) // true
    
    // 存储键值对到 map
    map2["WenFlower"] = 99
    
    // 获取key对应的value
    fmt.Println(map3["WenFlower"]) // 99
    
    // 获取 key 对应的值,以及是否存在对应的值 ok 为 true 表示存在,false 表示不存在
    value, ok := map3["WenFlower"]
    fmt.Println(value, ok) // 99, true
    
    // 删除对应的key
    delete(map3, "WenFlower")
    value, ok = map3["WenFlower"]
    fmt.Println(value, ok) // 0, false
    
    // 获取 map 的长度
    fmt.Println(len(map3)) // 2
    
    // 遍历 map
    for key, val := range map3 {
        fmt.Printf("map[%s] = %d\n", key, val)
    }
}

sync.Map

Golang 在 1.9 后提供的一个线程安全的键值对结构,但是使用几乎和 map 数据类型毫不相干

import (
	"fmt"
    "sync"
)

func main() {
    // 声明 sync.Map 就能直接使用
    var syncMap sync.Map
    
    // 存储key
    syncMap.Store("WenFlower", 99)
    syncMap.Store("Wen", 60)
    syncMap.Store("Flower", 59)
    
    // 获取 key 值
    fmt.Println(syncMap.Load("WenFlower")) // 99 true
    fmt.Println(syncMap.Load("WenFlower11")) // nil false
    
    // 删除 key 值
    syncMap.Delete("WenFlower")
    syncMap.Delete("WenFlower1111") // 删除不存在的 key 不会出现错误
    
    // 遍历
    syncMap.Range(func(key, value interface{}) bool {
        fmt.Printf("map[%s] = %d\n", key, value)
        return true
    })
}