• Go基础数据类型


    布尔类型

    布尔类型用于表示真假,类型名为bool,只有两个值true和false,占用一个字节宽度,0为false

    var (
        isTrue bool = true
        isFalse bool = false
    )
    

    逻辑运算

    (1)    与&&
    只有左右两边表达式结果都为true,运算结果才为true

    	fmt.Println(true && true)	//true
    	fmt.Println(true && false)	//false
    	fmt.Println(false && true)	//false
    	fmt.Println(false && false)	//false
    

    (2)    或||

    	fmt.Println(true || true)	//true
    	fmt.Println(true || false)	//true
    	fmt.Println(false || true)	//true
    	fmt.Println(false || false)	//false
    

    (3)    非!

    	fmt.Println(!true)	//false
    	fmt.Println(!false)	//true
    

    关系运算

    	fmt.Println(true == true)	//等于==
    	fmt.Println(true != true)	//不等于!=
    

    整数类型

    Go语言提供了5种有符号、5种无符号、1种指针、1种单字节、1种单个unicode字符(unicode码点),共13种整数类型,零值均为0

    类型名 字节宽度 说明&取值范围
    int 与平台有关,32位系统4字节,64位系统8字节 有符号整型
    uint 与平台有关,32 位系统 4 字节,64 位系统 8 字节 无符号整形
    int8 1 字节 用 8 位表示的有符号整型,取值范为:[-128, 127]
    int16 2字节 用 16 位表示的有符号整型,取值范围为:[-32768,32767]
    int32 4字节 用 32 位表示的有符号整型,取值范围为:[-2147483648,2147483647]
    int64 8字节 用 64 位表示的有符号整型,取值范围为:[-9223372036854775808,9223372036854775807]
    uint8 1 字节 用 8 位表示的有符号整型,取值范为:[0, 255]
    uint16 2字节 用 16 位表示的有符号整型,取值范围为:[0,65535]
    uint32 4字节 用 32 位表示的有符号整型,取值范围为:[0,4294967295]
    uint64 8字节 用 64 位表示的有符号整型,取值范围为:[0,18446744073709551615]
    rune 4字节 Unicode 码点,取值范围同int32
    byte 1 字节 字节类型,取值范围同 uint8
    uintptr 与平台有关,32 位系统 4 字节,64 位系统 8 字节 指针值的无符号整型

    字面量:

    十进制表示法: 以 10 为基数,采用 0-9 十个数字,逢 10 进位,如:10
    八进制表示法:以 8 为基数,采用 0-7 八个数字,逢 8 进位,使用 0 开头表示为八进制表示,如:010
    十六进制表示法:以 16 为基数,采用 0-9 十个数字和 A-F 六个字母,逢 16 进位,使用0X 开头表示为十六进制 ,如:0X10

    	// 分别打印十进制,八进制,十六进制的字面量
    	fmt.Println(10, 010, 0X10)	//10 8 16
    

    算术运算

    +、-、*、/、%、++、--,注意:针对/除数不能为0,且结果依然为整数

    	var n1, n2, n3 int = 1, -8, -2
    	var n4 uint = 4
    	// 算术运算
    	fmt.Println(n1 + n2)	//-7
    	fmt.Println(n1 - n2)	//9
    	fmt.Println(n1 * n2)	//-8
    	fmt.Println(n1 / n2)	//0 /向下取整
    	fmt.Println(n1 % n2)	//1
    
    	n3++
    	n4--
    	fmt.Println(n3, n4)	//-1 3
    

    关系运算

    、>=、 <、 <=、 ==、 !=

    	fmt.Println(1 > 2)
    	fmt.Println(1 >= 2)
    	fmt.Println(1 < 2)
    	fmt.Println(1 <= 2)
    	fmt.Println(1 == 2)
    	fmt.Println(1 != 2)
    

    位运算

    &、|、^、<<、 >>、 &^
    对于负整数在计算机中使用补码进行表示,对应正整数二进制表示取反+1
    针对左、右移的右操作数必须为无符号整型

    二进制表示法	
    	原码 正数
    	反码
    	补码	负数
    
    	// 位运算
    	// 2 二进制=> 0010
    	// 7 二进制=> 0111
    	// -2 二进制=> 1110  负整数在计算机中使用补码进行表示,对应正整数二进制表示取反+1
    	fmt.Println(4 & 2)	// 0100 & 0010 => 0000
    	fmt.Println(4 | 2)	// 0100 | 0010 => 0110
    	fmt.Println(4 ^ 2)	// 0100 ^ 0010 => 0110
    	fmt.Println(4 &^ 2)	// 0100 &^ 0010 => 0100
    	fmt.Println(4 << 2)	// 0100 <<移2位 => 0001 0000
    	fmt.Println(8 >> 2)	// 1000 >>移2位 => 0010
    

    赋值运算

    =、+=、-+、*=、/=、%=、&=、|=、^=、<<=、>>=

    	// 赋值运算
    	var n1, n2 int = 1, 2
    	n1 += n2	// n1 = n1 + n2
    	fmt.Println(n1)	//3
    	n1 <<= n2	// n1 = n1 << n2
    	fmt.Println(n1)	//12
    

    类型转换

    Go不会自动对数据类型转换,因此左、右操作数类型必须一致或int莫个字面量,可通过类型名(数据)的语法将数据转换为对应类型。需要大转小需要注意值截断和值溢出问题

    不建议这种类型转换写法:大转小,有符号转无符号,无符号转有符号
    
    // 类型转换
    	var n1, n2 int = 1, 4
    	fmt.Printf("%T %T %T %T %T %T\n", n1, uint(n1), n2, int(n2), uint8(n2), int64(n2))	//int uint int int uint8 int64
    

    fmt.Printf进行格式化参数输出, 占位符:

    %T    变量名类型
    %b    二进制
    %c    字符
    %d    十进制
        %+d    表示对正整数带+符号
        %nd    表示最小占位n个宽度且右对齐
        %-nd    表示最小占位n个宽度且左对齐
        %0nd    表示最小占位n个宽度且右对齐,空字符使用0填充
    %o    八进制
        %#o    带0的前缀
    %x、%X 十六进制
        %#x(%#X)带0x(0X)的前缀
    %U    Unicode码点
        %#U    带字符的Unicode码点
    %q    带单引号的字符
    
    // fmt打印
    	var (
    		n1	int = 10
    		n2	int	= -10
    		n3	byte = 'a'
    		n4  rune = '虎'
    	)
    	fmt.Printf("%d %b %o %x %X %#o %#x %#X\n", n1, n1, n1, n1, n1, n1, n1, n1,)	//10 1010 12 a A 012 0xa 0XA
    	fmt.Printf("|%d|%+d|%10d|%-10d|%010d|%+-10d|%+010d|\n", n1, n1, n1, n1, n1, n1, n1)	//10|+10|        10|10        |0000000010|+10       |+000000010
    	fmt.Printf("%d|%+d|%10d|%-10d|%010d|%+-10d|%+010d|\n", n2, n2, n2, n2, n2, n2, n2)	//-10|-10|       -10|-10       |-000000010|-10       |-000000010
    	fmt.Printf("%c %c %q %q\n", n3, n4, n3, n4)	//a 虎 'a' '虎'
    	fmt.Printf("%U %#U\n", n4, n4)	//U+864E U+864E '虎'
    

    浮点型

    浮点数用于表示带小数的数字,Go提供float32和float64两种浮点类型,非精确值类型,零值0.0

    主要是为了表示小数,也可细分为float32和float64两种。浮点数能够表示的范围可以从很小到很巨大,这个极限值范围可以在math包中获取,math.MaxFloat32表示float32的最大值,大约是3.4e38,math.MaxFloat64大约是1.8e308,两个类型最小的非负值大约是1.4e-45和4.9e-324。

    float32大约可以提供小数点后6位的精度,作为对比,float64可以提供小数点后15位的精度。通常情况应该优先选择float64,因此float32的精确度较低,在累积计算时误差扩散很快,而且float32能精确表达的最小正整数并不大,因为浮点数和整数的底层解释方式完全不同。

    类型 长度
    float32 IEEE-754 32位浮点型数
    float64 IEEE-754 64位浮点型数

    字面量

    十进制表示法:3.1415926
    科学计数法:1e-5

    格式

    	// 浮点型
    	var (
    		f1 float32 = 3.1415926
    		f2 float32 = 3E-3
    		f3 float64 = 3.1E10
    	)
    

    算术运算

    +、-、*、/、++、--
    注意:针对/除数不能为0

    // 浮点型-算术运算
    	var (
    		f1 float32 = 3.1415926
    		f2 float32 = 3E-3
    	)
    	fmt.Println(f2)	//0.003
    	fmt.Println(f1 + f2)	//3.1445925
    	fmt.Println(f1 - f2)	//3.1385925
    	fmt.Println(f1 * f2)	//0.009424778
    	fmt.Println(f1 / f2)	//1047.1975
    	f1++
    	f2--
    	fmt.Println(f1, f2)	//4.1415925 -0.997
    

    关系运算

    、>=、<、<=
    浮动型不能进行==或者!=比较,可选择使用两个浮点数的差在一定区间内则认为相等

    	// 浮点型-关系运算
    	var (
    		f1 float32 = 3.1415926
    		f2 float32 = 3E-3
    	)
    	fmt.Println(f1 > f2)
    	fmt.Println(f1 >= f2)
    	fmt.Println(f1 < f2)
    	fmt.Println(f1 <= f2)
    

    赋值运算

    =、-=、*=、/=

    var (
    		f1 float32 = 3.1415926
    		f2 float32 = 3E-3
    	)
    	f1 += f1
    	f2 -= f2
    	fmt.Println(f1)
    	fmt.Println(f2)
    

    类型转换

    Go不会自动对数据类型转换,因此左、右操作数类型必须一致或int莫个字面量,可通过类型名(数据)的语法将数据转换为对应类型。需要注意值截断和值溢出问题

    var (
    		f1 float32 = 3.1415926
    	)
    
    	fmt.Printf("%T %T\n", f1, float64(f1))
    

    fmt.Printf进行格式化参数输出,占位符:

    %f、%F    十进制表示法
    %n.mf 表示最小占n个宽度并且最多保留m位小数
    %e、%E    科学计数法表示
    %g、%G    自动选择最紧凑得表示方法%e\%E和%f\%F
    
    //  fmt.Printf打印
    	var (
    		f1 float32 = 3.1415926
    		f3 float32 = 3E-3
    	)
    
    	fmt.Printf("%f %f %F %F\n", f1, f3, f1, f3)	//3.141593 0.003000 3.141593 0.003000
    	fmt.Printf("%e %e %E %E\n", f1, f3, f1, f3)	//3.141593e+00 3.000000e-03 3.141593E+00 3.000000E-03
    	fmt.Printf("%g %g %G %G\n", f1, f3, f1, f3)	//3.1415925 0.003 3.1415925 0.003
    	fmt.Printf("|%5.2f| |%5.2f|\n", f1, f3)	//| 3.14| | 0.00|
    

    复数型

    Go 提供 complex64 和 complex128 两种复数类型,针对 complex64 复数的实部和虚部均使用
    float32,针对 complex128 复数的实部和虚部均使用 float64

    类型 长度
    complex64 32位实数和虚数
    complex128 64位实数和虚数

    字面量

    十进制表示法:1 + 2i,i*i = -1; 1为实部,2为虚部

    常用函数

    complex: 工厂函数,通过两个参数创建一个复数

    real: 用于获取复数的实部

    imag:用于获取复数的虚部

    	//  复数
    	var (
    		c1 complex64 = 1 + 2i
    		c2 complex64 = complex(3, 4)
    	)
    
    	fmt.Println(c1 + c2)	//(4+6i)
    	fmt.Println(real(c1), imag(c1))	//1 2
    

    字符串类型

    Go语言内置了字符串类型,使用类型名string表示,零为空字符串""

    只读的Unicode字节序列,Go语言使用UTF-8格式编码Unicode字符,每个字符对应一个rune类型。一旦字符串变量赋值之后,内部的字符就不能修改,英文是一个字节,中文是三个字节。

    字面量

    ​ 可解析字符串:通过双引号"来创建,不包含多行,支持特殊字符转义序列

    ​ 原生字符串:通过反引号`来创建,包含多行,不支持特殊字符转义序列

    特殊字符

    	\\	反斜杠
    	\'	单引号
    	\"	双引号
    	\a	响铃
    	\b	退格
    	\f	换页
    	\n	换行
    	\r	回车
    	\t	制表符
    	\v	垂直制表符
    	\ooo	3个8位数字给定的八进制码点的Unicode字符(不能超过\377)
    	\uhhhh	4个16位数字给定的十六进制码点的Unicode字符
    	\Uhhhhhhhh	8个32位数字给定的十六进制码点的Unicode字符
    	\xhh	2个8位数字给定的十六进制码点的Unicode字符
    
    //  字符串
    	var (
    		s1 string = "aaa\nbbb"
    		s2 string = `aaa\nbbb`
    		s3 string = `aaa
    							bbb`
    		s4 string = "qwertyuiopasdfghjklzxcvbnm"
    		s5 string = "我爱中国"
    	)
    
    	fmt.Println(s1)
    	fmt.Println(s2)	//aaa\nbbb
    	fmt.Println(s3)	/*aaa
    													bbb*/
    
    	fmt.Println(s4)
    	fmt.Println(s5)	//我爱中国
    

    常用操作

    字符串拼接 +

    关系运算符 >、>=、<、<=、==、!=

    赋值运算符 +=

    索引 s[index],针对只包含ascii字符的字符串

    切片 s[start:end],针对只包含ascii字符的字符串

    //  字符串
    	var (
    		s1 string = "aaa\nbbb"
    		s2 string = `aaa\nbbb`
    		s3 string = `aaa
    							bbb`
    		s4 string = "qwertyuiopasdfghjklzxcvbnm"
    		s5 string = "我爱中国"
    	)
    
    	fmt.Println(s4+"aaaaaaaaaaaaaaaasssdscas")	//qwertyuiopasdfghjklzxcvbnmaaaaaaaaaaaaaaaasssdscas
    	s5 += "--来自南方"
    	fmt.Println(s5)	//我爱中国--来自南方
    	fmt.Println(s1 == s2)	//false
    	fmt.Println(s1 != s3)	//true
    	fmt.Println("abc" > "abe")	//false
    	fmt.Println("abc" >= "abe")	//false
    	fmt.Println("abc" <= "abe")	//true
    
    	fmt.Println(s4[0])	//索引0的ascii:113
    	// 切片前包后不包
    	fmt.Println(s4[:], s4[3:], s4[:8], s4[3:8])	//qwertyuiopasdfghjklzxcvbnm rtyuiopasdfghjklzxcvbnm qwertyui rtyui
    

    常用函数

    ​ len 获取字符串长度(针对只包含ascii字符的字符串)

    ​ string 将byte或rune数组转换为字符串

    使用fmt.Printf进行格式化参数输出,占位符:

    %s	基本的字符串输出
    
    %d	十进制
    
    	//  字符串
    	var (
    		s1 string = "aaa\nbbb"
    		s5 string = "我爱中国"
    	)
    
    	fmt.Printf("%s len %d\n", s1, len(s1))
    	fmt.Printf("%s len %d\n", s5, len(s5))
    

    类型转换

    string转int:    int, err := strconv.Atoi(string)
    string转int64:  int64, err := strconv.ParseInt(string, 10, 64)
    int转string:    string := strconv.Itoa(int)
    int64转string:  string := strconv.FormatInt(int64, 10)
    

    枚举类型

    常使用iota生成器用于初始化一系列相同规则的常量,批量声明常量的第一个常量的使用iota进行赋值,此时 iota 被重置为 0,其他常量省略类型和赋值,在每初始化一个常量则加 1

    const (
    	i1 int = iota
    	i2
    	i3 int = iota
    	i4
    )
    
    func main() {
    	//  枚举类型
    	const (
    		i5 = iota
    		i6
    		i7 = 7
    		i8 = iota
    		i9
    	)
    
    	fmt.Println(i1, i2, i3, i4, i5, i6, i7, i8, i9)	//0 1 2 3 0 1 7 3 4
    
    }
    

    指针类型(Pointer)

    一个指针变量可以指向任何一个值的内存地址。它指向那个值的内存地址,在 32 位机器上占用 4 个字节,在 64 位机器上占用 8 个字节,并且与它所指向的值的大小无关。当然,可以声明指针指向任何类型的值来表明它的原始性或结构性;你可以在指针类型前面加上号(前缀)来获取指针所指向的内容,这里的号是一个类型更改器。使用一个指针引用一个值被称为间接引用。

    当一个指针被定义后没有分配到任何变量时,它的值为 nil,表示空指针

    一个指针变量通常缩写为 ptr。

    符号 ““ 可以放在一个指针前,如 “intP”,那么它将得到这个指针指向地址上所存储的值;这被称为反引用(或者内容或者间接引用)操作符;另一种说法是指针转移。

    对于任何一个变量 var, 如下表达式都是正确的:var == *(&var)

    注意事项:
    你不能得到一个数字或常量的地址,下面的写法是错误的。
    
    //例如:
    const i = 5
    ptr1 := &i // error: cannot take the address of i
    ptr2 := &10 // error: cannot take the address of 10
    

    所以说,Go 语言和 C、C++ 以及 D 语言这些低级(系统)语言一样,都有指针的概念。

    但是对于经常导致 C 语言内存泄漏继而程序崩溃的指针运算(所谓的指针算法,如:pointer+2,移动指针指向字符串的字节数或数组的某个位置)是不被允许的。

    Go 语言中的指针保证了内存安全,更像是 Java、C# 和 VB.NET 中的引用。

    因此 c = *p++ 在 Go 语言的代码中是不合法的。

    指针的一个高级应用是你可以传递一个变量的引用(如函数的参数),这样不会传递变量的拷贝。指针传递是很廉价的,只占用 4 个或 8 个字节。当程序在工作中需要占用大量的内存,或很多变量,或者两者都有,使用指针会减少内存占用和提高效率。被指向的变量也保存在内存中,直到没有任何指针指向它们,所以从它们被创建开始就具有相互独立的生命周期。

    另一方面(虽然不太可能),由于一个指针导致的间接引用(一个进程执行了另一个地址),指针的过度频繁使用也会导致性能下降。

    指针也可以指向另一个指针,并且可以进行任意深度的嵌套,导致你可以有多级的间接引用,但在大多数情况这会使你的代码结构不清晰。

    如我们所见,在大多数情况下 Go 语言可以使程序员轻松创建指针,并且隐藏间接引用,如:自动反向引用。

    对一个空指针的反向引用是不合法的,并且会使程序崩溃:

    package main
    func main() {
        var p *int = nil
        *p = 0
    }
    // 结果err: panic: runtime error: invalid memory address or nil pointer dereference
    // 紧急:运行时错误:无效的内存地址或nil指针取消引用
    

    指针的使用方法:

    • 定义指针变量;
    • 为指针变量赋值;
    • 访问指针变量中指向地址的值;
    • 在指针类型前面加上*号来获取指针所指向的内容。
    package main
    
    import "fmt"
    
    func main() {
        var a, b int = 20, 30 // 声明实际变量
        var ptra *int         // 声明指针变量
        var ptrb *int = &b
        
        ptra = &a // 指针变量的存储地址 // 取出a的地址赋值给ptra => 取引用
        
        fmt.Printf("a  变量的地址是: %x\n", &a)
        fmt.Printf("b  变量的地址是: %x\n", &b)
        
        // 指针变量的存储地址
        fmt.Printf("ptra  变量的存储地址: %x\n", ptra)
        fmt.Printf("ptrb  变量的存储地址: %x\n", ptrb)
        
        // 使用指针访问值
        fmt.Printf("*ptra  变量的值: %d\n", *ptra)  // 获取ptra内存地址中对应的存储的值 => 解引用
        fmt.Printf("*ptrb  变量的值: %d\n", *ptrb)	// 获取ptrb内存地址中对应的存储的值 => 解引用
    }
    

    数组值类型

    package main
    
    import "fmt"
    
    func main() {
    	nums := [5]int{1, 2, 3, 4, 5}
    	nums2 := nums
    
    	fmt.Println(nums, nums2)
    
    	nums2[0] = 100
    	fmt.Println(nums, nums2) // nums的[0]不受影响
        // 指针
        // 值类型
        // int, float, bool, string => 值类型
        // 赋值 原有的数据复制一份给新的变量
        // 两个变量之间没有任何联系
        // 对nums进行任何修改都不会影响nums2
        // 对nums2进行任何修改也不会影响nums
        
        var numsPoint *[5]int = &nums  // 取出nums数组地址赋值给numsPoint => 取引用
    	fmt.Printf("%T\n", numsPoint)
    	numsPoint[0] = 100
    	fmt.Println(nums, numsPoint) // 指针影响
    }
    
  • 相关阅读:
    [专项]tcp状态机,为什么3次握手(很好)(done)
    Win7系统如何创建计划任务的小技巧(图文)
    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
    Java项目 使用MyEclipse打包生成jar文件方法
    excel插入柱形图和插入置信值
    关于Virtual Box虚拟机里的系统不能启动的解决方法
    html文件的中文乱码问题与在浏览器中的显示 .
    Windows的计划任务
    不能为虚拟电脑 Fedora1 打开一个新任务.
    bat 通过bat脚本来每隔一段时间运行jar包
  • 原文地址:https://www.cnblogs.com/Otiger/p/13701181.html
Copyright © 2020-2023  润新知