• golang学习笔记系列之基本数据类型


    基本数据类型

    在go语言中,数据类型用于声明函数和变量。

    数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才去申请大内存,需要小数据的时候就去申请小的内存,就可以充分利用空间。

    go语言按类别有以下几种数据:

    类型描述
    布尔类型布尔类型的值只可以是常量true或false。一个简单的例子:var flag=true
    数字类型数字类型包括整型int,浮点型float32和浮点型float64;同时支持复数。(注意:不能用0或者非0表示条件判断
    字符串类型字符串就是一串固定长度的字符连接起来的字符序列。go语言的字符串是由单个字节连接起来的,go语言的字符串的字节使用utf8编码标识unicode文本。
    派生类型派生类型包括:指针类型,数组类型,切片类型,结构体类型,channel类型,接口类型,map类型等等

    整数类型

    go语言也有基于架构的类型,例如:int,uint和uintptr。

    类型描述
    uint8无符号8位整型(0到255)
    uint16无符号16位整数(0到65535)
    uint32无符号32位整数(0到4294967295)
    uint64无符号64位整数(0到18446744073709551616)
    int8有符号8位整数(-128到127)
    int16有符号16位整数(-32768到32767)
    int32有符号32位整数(-2147483648到2147483647)
    int64有符号64位整数(-9223372036854775808到9223372036854775807)
    package main
    
    import (
    	"fmt"
    	"math"
    	"unsafe"
    )
    
    func main() {
    
    	var a uint8
    	var b uint16
    	var c uint32
    	var d uint64
    
    	fmt.Printf("a: %v %T %dB  %v~%v\n", a, a, unsafe.Sizeof(a), 0, math.MaxUint8)
    	fmt.Printf("b: %v %T %dB  %v~%v\n", b, b, unsafe.Sizeof(b), 0, math.MaxUint16)
    	fmt.Printf("c: %v %T %dB  %v~%v\n", c, c, unsafe.Sizeof(c), 0, math.MaxUint32)
    	fmt.Printf("d: %v %T %dB  %v~%v\n", d, d, unsafe.Sizeof(d), 0, math.MaxInt64)
    
    	var e int8
    	var f int16
    	var g int32
    	var h int64
    	fmt.Printf("e: %v %T %dB  %v~%v\n", e, e, unsafe.Sizeof(e), math.MinInt8, math.MaxInt8)
    	fmt.Printf("f: %v %T %dB  %v~%v\n", f, f, unsafe.Sizeof(f), math.MinInt16, math.MaxInt16)
    	fmt.Printf("g: %v %T %dB  %v~%v\n", g, g, unsafe.Sizeof(g), math.MinInt32, math.MaxInt32)
    	fmt.Printf("h: %v %T %dB  %v~%v\n", h, h, unsafe.Sizeof(h), math.MinInt64, math.MaxInt64)
    
    	var i float32
    	var j float64
    	fmt.Printf("i: %v %T %dB  %v~%v\n", i, i, unsafe.Sizeof(i), -math.MaxFloat32, math.MaxFloat32)
    	fmt.Printf("j: %v %T %dB  %v~%v\n", j, j, unsafe.Sizeof(j), -math.MaxFloat64, math.MaxFloat64)
    
    	var k complex64
    	var l complex128
    	fmt.Printf("k: %v %T %dB  \n", k, k, unsafe.Sizeof(k))
    	fmt.Printf("l: %v %T %dB  \n", l, l, unsafe.Sizeof(l))
    
    }
    
    /*
    a: 0 uint8 1B  0~255
    b: 0 uint16 2B  0~65535
    c: 0 uint32 4B  0~4294967295
    d: 0 uint64 8B  0~9223372036854775807
    e: 0 int8 1B  -128~127
    f: 0 int16 2B  -32768~32767
    g: 0 int32 4B  -2147483648~2147483647
    h: 0 int64 8B  -9223372036854775808~9223372036854775807
    i: 0 float32 4B  -3.4028234663852886e+38~3.4028234663852886e+38
    j: 0 float64 8B  -1.7976931348623157e+308~1.7976931348623157e+308
    k: (0+0i) complex64 8B  
    l: (0+0i) complex128 16B 
    */
    
    
    • 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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    进制的相互转换

    package main
    
    import "fmt"
    
    func main() {
    
    	//十进制的数
    	a := 10
    
    	fmt.Printf("a的十进制表示a: %d\n", a)
    	fmt.Printf("a的二进制表示a: %b\n", a)
    	fmt.Printf("a的八进制表示a: %o\n", a)
    	fmt.Printf("a的十六进制表示a: %x\n", a)
    
    	//定义一个八进制的数 以0开头
    	b := 077
    
    	fmt.Printf("b的十进制表示a: %d\n", b)
    	fmt.Printf("b的二进制表示a: %b\n", b)
    	fmt.Printf("b的八进制表示a: %o\n", b)
    	fmt.Printf("b的十六进制表示a: %x\n", b)
    
    	//定义一个十六进制的数 以0x开头
    	c := 0x111
    
    	fmt.Printf("c的十进制表示a: %d\n", c)
    	fmt.Printf("c的二进制表示a: %b\n", c)
    	fmt.Printf("c的八进制表示a: %o\n", c)
    	fmt.Printf("c的十六进制表示a: %x\n", c)
    
    }
    
    
    • 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
    • 30
    • 31
    • 32

    浮点类型

    类型描述
    float32IEEE-754 32位浮点型数
    float64IEEE-754 64位浮点型数
    complex6432位实数和虚数
    complex12864位实数和虚数

    其他数字类型

    类型描述
    byte类似uint8
    rune类似int32

    字符串类型

    在go语言中,字符串使用双引号""或者反引号来创建。双引号用来创建可解析的字符串,支持转义,但不能用来引用多行;反引号用来创建原生的字符串,可由多行组成,但不支持转义,并且可以包含除了反引号外其他所有字符。双引号创建可解析的字符串应用最广泛,反引号用来创建原生的字符串多用于书写多行消息,HTML以及正则表达式。

    字符串的拼接
    package main
    
    import (
    	"bytes"
    	"fmt"
    	"strings"
    )
    
    func main() {
    
    	//单行字符串 支持转义
    	a := "hello world"
    
    	//多行字符串 不支持转义
    	b := `
    			

    hello

    `
    fmt.Printf("a: %v\n", a) fmt.Printf("b: %v\n", b) //字符串的拼接 s1 := "hello" s2 := "world" //1.加号拼接 res1 := s1 + " " + s2 fmt.Printf("s: %v\n", res1) //2.字符串格式化 Sprintf res2 := fmt.Sprintf("%s %s", s1, s2) fmt.Printf("res2: %v\n", res2) //3.strings.join() /* join会根据字符串数组得到内容,计算出一个拼接之后的字符串的长度,然后申请对应大小的内存,一个一个字符填入, 在已有一个数组的情况下,这种效率会很高,但是本来没有,去构造这个数组的代价也很高 */ res3 := strings.Join([]string{s1, s2}, " ") //第一个参数是字符串数组,第二个参数是连接符 fmt.Printf("res3: %v\n", res3) //4.buffer.WriteString() /* 这个比较理想,可以当成可变字符串使用,对内存的增长也有优化,如果能预估字符串的长度,还可以使用buffer.Grow()接口来设置capacity 同时这是直接写到缓冲区,因此效率比较高 */ var buffer bytes.Buffer buffer.WriteString(s1) buffer.WriteString(s2) fmt.Printf("buffer.String(): %v\n", buffer.String()) }
    • 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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    转义字符

    go语言的字符串常见的转义字符包含回车,换行,单双引号,制表符

    转义符含义
    \r回车符号
    \n换行符
    \t制表符(tab键,或者四个空格)
    \’单引号
    \"双引号
    \\反斜杠
    切片操作
    //切片操作
    	s := "I am a student."
    	m, n := 2, 4
    
    	fmt.Printf("s[m:n]: %v\n", s[m:n]) //获取字符串s索引位置从m到n-1的值
    	fmt.Printf("s[:n]: %v\n", s[:n])   //获取字符串s索引位置从0到n-1的值
    	fmt.Printf("s[m:]: %v\n", s[m:])   //获取字符串s索引位置从m到len(s)-1的值
    	fmt.Printf("s[:]: %v\n", s[:])     //获取字符串s
    	fmt.Printf("s[m]: %v\n", s[m])     //获取字符串s索引位置m的字符的ascii值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    字符串的一些常用方法
    方法描述
    len(s)获取字符串s的长度
    +或者fmt.Sprintf拼接字符串
    strings.Split(s,seq)用分隔符seq分割字符s
    strings.Contains(s,subs)查询字符串s中是否包含子串subs
    strings.HasPrefix(s,prefix)/strings.HasSuffix(s,suffix)判断前/后缀是否是指定的字符串
    strings.Index(s,subs)/strings.LastIndex(s,subs)查询子串subs在s中第一次(最后一次)出现的索引位置,若没有则返回-1
    strings.join(s_arr,seq)将字符串数组用seq拼接成一个字符串
    //分割字符串
    	fmt.Printf("strings.Split(s, \" \"): %v\n", strings.Split(s, " "))
    
    	//查询某个字符串是否包含指定的字符串
    	fmt.Printf("strings.Contains(s, \"student\"): %v\n", strings.Contains(s, "student"))
    
    	//判断前缀是否是指定的字符串
    	fmt.Printf("strings.HasPrefix(s, \"hello\"): %v\n", strings.HasPrefix(s, "hello"))
    
    	//判断后缀是否是指定的字符串
    	fmt.Printf("strings.HasSuffix(s, \"student.\"): %v\n", strings.HasSuffix(s, "student."))
    
    	//查找指定字符串第一次出现的索引位置
    	fmt.Printf("strings.Index(s, \"a\"): %v\n", strings.Index(s, "aaa"))
    
    	//查找指定字符串最后一次出现的索引位置
    	fmt.Printf("strings.LastIndex(s, \"a\"): %v\n", strings.LastIndex(s, "a"))
    
    	//拼接字符串数组
    	fmt.Printf("strings.Join([]string{\"i\", \"am\", \"a\", \"student.\"}, \" \"): %v\n", strings.Join([]string{"i", "am", "a", "student."}, " "))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行结果

    strings.Split(s, " "): [I am a student.]
    strings.Contains(s, "student"): true
    strings.HasPrefix(s, "hello"): false
    strings.HasSuffix(s, "student."): true
    strings.Index(s, "a"): -1
    strings.LastIndex(s, "a"): 5
    strings.Join([]string{"i", "am", "a", "student."}, " "): i am a student.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    格式化输出

    普通占位符
    占位符说明举例
    %v相应值的默认格式。fmt.Printf(“a: %v\n”, 100) ----> a:100
    %#v会打印出数据的完整格式。tom := studnet{“Tom”}fmt.Printf(“tom: %#v\n”, tom) ---->tom: main.studnet{Name:“Tom”}
    %T相应值的类型。fmt.Printf(“a: %T\n”, 100) ----> a:int
    %%输出%。fmt.Printf(“%%”) ---->%
    //相应数据的默认格式
    a := 10
    fmt.Printf("a: %#v\n", a)
    
    tom := studnet{"Tom"}
    //数据的完整格式
    fmt.Printf("tom: %#v\n", tom)
    
    //%
    fmt.Printf("%%\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果

    a: 10
    tom: main.studnet{Name:"Tom"}
    %
    
    • 1
    • 2
    • 3
    布尔占位符
    占位符说明举例
    %t输出true或false。fmt.Printf(“flag: %t\n”, true) ---->true
    //布尔占位符
    flag := true
    fmt.Printf("flag: %t\n", flag)
    
    • 1
    • 2
    • 3

    运行结果

    flag: true
    
    • 1
    整数占位符
    占位符说明举例
    %b输出二进制表示fmt.Printf(“%b\n”, 10) ---->1010
    %c相应的Unicode码值所表示的码符fmt.Printf(“%c\n”,97) ---->a
    %d输出十进制表示fmt.Printf(“%d\n”, 10) ---->10
    %o输出八进制表示fmt.Printf(“%o\n”, 10) ---->12
    %x十六进制表示(小写字母)fmt.Printf(“%x\n”, 10) ---->a
    %X十六进制表示(大写字母)fmt.Printf(“%X\n”, 10) ---->A
    %q单引号围绕的字符字面值,由go语法安全的转义fmt.Printf(“%q\n”, 10) ---->‘\n’
    %UUnicode格式:U+1234等同于“U+%04X”fmt.Printf(“%U\n”, 10) ---->U+000A
    //二进制输出
    fmt.Printf("%b\n", 10)
    
    //相应的Unicode码值对应的码符
    fmt.Printf("%c\n", 97)
    
    //八进制
    fmt.Printf("%o\n", 10)
    
    //十六进制 小写字母
    fmt.Printf("%x\n", 10)
    
    //十六进制 大写字母
    fmt.Printf("%X\n", 10)
    
    fmt.Printf("%q\n", 10)
    fmt.Printf("%U\n", 10)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行结果

    1010
    a
    12
    a
    A
    '\n'
    U+000A
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    浮点数和复数占位符
    占位符说明举例
    %b无小数部分的,指数为二的幂的科学计数法,与strconv.FormatFloat的’b’转换格式一样fmt.Printf(“%b\n”, 10.1) ---->5685794529555251p-49
    %e科学计数法(小写字母)fmt.Printf(“%e\n”, 10.1) ---->1.010000e+01
    %E科学计数法(大写字母)fmt.Printf(“%E\n”, 10.1) ---->1.010000E+01
    %f有小数点而无指数fmt.Printf(“%5.2f\n”, 10.1) ---->10.10(总长度为5,小数点两位)
    %g根据情况选择%e或%f以产生更紧凑的输出(无末尾的0)fmt.Printf(“%g\n”, 10.10000) ---->10.1
    %G根据情况选择%E或%f以产生更紧凑的输出(无末尾的0)fmt.Printf(“%G\n”, 10.000+2.0600i) ---->(10+2.06i)
    //浮点数和复数
    fmt.Printf("%b\n", 10.1)
    fmt.Printf("%e\n", 10.1)
    fmt.Printf("%E\n", 10.1)
    fmt.Printf("2%5.2f2\n", 10.1)
    fmt.Printf("%g\n", 10.10000)
    fmt.Printf("%G\n", 10.000+2.0600i)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果

    5685794529555251p-49
    1.010000e+01
    1.010000E+01
    210.102
    10.1
    (10+2.06i)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    字符串与字节切片占位符
    占位符说明举例
    %s输出字符串表示(string类型或[]byte类型)fmt.Printf(“[]byte{“hello”, “world”}: %s\n”, []byte(“hello”)) ---->[]byte{“hello”, “world”}: hello
    %q双引号围绕的字符串,由go语言安全地转义fmt.Printf(““hello”: %q\n”, “hello”) ---->“hello”
    %x十六进制,小写字母,每字节两个字符fmt.Printf(““hello”: %x\n”, “hello”) ---->“hello”: 68656c6c6f
    %X十六进制,大写字母,每字节两个字符fmt.Printf(““hello”: %X\n”, “hello”) ---->“hello”: 68656C6C6F
    //字符串
    fmt.Printf("[]byte{\"hello\", \"world\"}: %s\n", []byte("hello"))
    fmt.Printf("\"hello\": %q\n", "hello")
    fmt.Printf("\"hello\": %x\n", "hello")
    fmt.Printf("\"hello\": %X\n", "hello")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果

    []byte{"hello", "world"}: hello
    "hello": "hello"
    "hello": 68656c6c6f
    "hello": 68656C6C6F
    
    • 1
    • 2
    • 3
    • 4
    指针占位符
    占位符说明举例
    %p十六进制表示,输出指针所指向的地址h := 100 p_h := &h fmt.Printf(“%p\n”, &h) fmt.Printf(“%p\n”, p_h) ---->两个输出是一样的:0xc0000ba018,都是输出的h的地址
    h := 100
    p_h := &h
    fmt.Printf("h: %p\n", &h)
    fmt.Printf("p_h: %p\n", p_h)
    
    • 1
    • 2
    • 3
    • 4

    运行结果

    h: 0xc0000140f8
    p_h: 0xc0000140f8
    
    • 1
    • 2

    golang运算符

    go语言内置的运算符有:

    • 算术运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
    • 赋值运算符
    算术运算符
    运算符描述
    +相加
    -相减
    *相乘
    /相除
    %取模(求余)

    注意:++(自增)和–(自减)在go语言中是单独的语句,并不是运算符。

    a := 100
    	b := 200
    	//算术运算符
    	res := a + b
    	fmt.Printf("res: %v\n", res)
    
    	res = a - b
    	fmt.Printf("res: %v\n", res)
    
    	res = a * b
    	fmt.Printf("res: %v\n", res)
    
    	res = a / b
    	fmt.Printf("res: %v\n", res)
    
    	res = a % b
    	fmt.Printf("res: %v\n", res)
    	a++
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果

    res: 300
    res: -100
    res: 20000
    res: 0
    res: 100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    关系运算符
    运算符描述
    ==检查两个值是否相等,返回true或false
    !=检查两个值是否不相等,返回true或false
    >检查左边的值是否大于右边的值,返回true或false
    >=检查左边的值是否大于等于右边的值,返回true或false
    <检查左边的值是否小于右边的值,返回true或false
    <=检查左边的值是否小于等于右边的值,返回true或false
    // 关系运算符
    	var res2 bool
    
    	res2 = a == b
    	fmt.Printf("res2: %v\n", res2)
    
    	res2 = a > b
    	fmt.Printf("res2: %v\n", res2)
    
    	res2 = a >= b
    	fmt.Printf("res2: %v\n", res2)
    
    	res2 = a < b
    	fmt.Printf("res2: %v\n", res2)
    
    	res2 = a <= b
    	fmt.Printf("res2: %v\n", res2)
    
    	res2 = a != b
    	fmt.Printf("res2: %v\n", res2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行结果

    res2: false
    res2: false
    res2: false
    res2: true
    res2: true
    res2: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    逻辑运算符
    运算符描述
    &&逻辑and运算符。只有两边的操作数都为true才返回true,否则返回false。
    ||逻辑or运算符。只要有一个操作数为true就返回true,否则返回false。
    !逻辑not运算符。取相反的结果。
    //逻辑运算
    	var res3 bool
    	res3 = true && true
    	fmt.Printf("res3: %v\n", res3)
    	res3 = true || false
    	fmt.Printf("res3: %v\n", res3)
    	res3 = !res3
    	fmt.Printf("res3: %v\n", res3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    res3: true
    res3: true
    res3: false
    
    • 1
    • 2
    • 3
    位运算符

    位运算是对整数在内存中的二进制位进行操作。

    运算符描述
    &参与运算的两个数各对应的二进位相与。(两位均为1才为1)
    |参与运算的两个数各对应的二进位相或。(两位只要有一个为1就为1)
    ^参与运算的两个数各对应的二进位异或。(当相对应的二进位相异时,结果才为1,否则为0)
    <<左移n位就是乘以2的n次方。a<
    <<右移n位就是除以2的n次方。a>>b是把a的各二进位全部右移b位。
    //位运算
    	aa := 10
    	bb := 11
    	fmt.Printf("aa: %b\n", aa)
    	fmt.Printf("bb: %b\n", bb)
    
    	res4 := aa & bb
    	fmt.Printf("res4:%b  %v\n", res4, res4)
    	res4 = aa | bb
    	fmt.Printf("res4:%b  %v\n", res4, res4)
    	res4 = aa ^ bb
    	fmt.Printf("res4:%b  %v\n", res4, res4)
    
    	res4 = aa << 2
    	fmt.Printf("res4:%b  %v\n", res4, res4)
    	res4 = aa >> 1
    	fmt.Printf("res4:%b  %v\n", res4, res4)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行结果

    aa: 1010
    bb: 1011
    res4:1010  10
    res4:1011  11
    res4:1  1
    res4:101000  40
    res4:101  5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    赋值运算符
    运算符描述
    =简单的赋值运算符,将等号右边的结果赋值给左边的变量。
    +=相加后再赋值
    -=相减后再赋值
    *=相乘后再赋值
    /=相除后再赋值
    %=取模后再赋值
    <<=左移后再赋值
    >>=右移后再赋值
    &=按位与后赋值
    |=按位或后赋值
    ^=异或后赋值

    同步更新于个人博客系统:golang学习笔记系列之基本数据类型

  • 相关阅读:
    HTTP 报文详解
    数码品牌这样做,教你实现用户增长
    基于MCU_USB的虚拟串口助手实现
    js 删除树状图无用数据,如果子级没有数据则删除
    C语言学习——数组初学
    Spring框架概述 --- 常用注解
    python文件的读取
    ZooKeeper系列:实现分布式锁
    重温C语言十五---C语言文件管理操作
    js中的同步任务、异步任务、宏任务、微任务
  • 原文地址:https://blog.csdn.net/max_LLL/article/details/126798231