03-Go语言之数据类型

内容目录

  • 整型
  • 浮点类型
  • 复数
  • 布尔值
  • 字符串
  • byte类型和rune类型
  • if循环

内容详细

整型

  • 整型分为以下两个大类: 按长度分为:int8、int16、int32、int64 对应的无符号整型:uint8、uint16、uint32、uint64

    其中,uint8就是我们熟知的byte型,int16对应C语言中的short型,int64对应C语言中的long型。

    类型 描述
    uint8 无符号 8位整型 (0 到 255)
    uint16 无符号 16位整型 (0 到 65535)
    uint32 无符号 32位整型 (0 到 4294967295)
    uint64 无符号 64位整型 (0 到 18446744073709551615)
    int8 有符号 8位整型 (-128 到 127)
    int16 有符号 16位整型 (-32768 到 32767)
    int32 有符号 32位整型 (-2147483648 到 2147483647)
    int64 有符号 64位整型 (-9223372036854775808 到 9223372036854775807)
  • 特殊整型

    类型 描述
    uint 32位操作系统上就是uint32,64位操作系统上就是uint64
    int 32位操作系统上就是int32,64位操作系统上就是int64
    uintptr 无符号整型,用于存放一个指针

注意: 在使用intuint类型时,不能假定它是32位或64位的整型,而是考虑intuint可能在不同平台上的差异。

注意事项 获取对象的长度的内建len()函数返回的长度可以根据不同平台的字节长度进行变化。实际使用中,切片或 map 的元素数量等都可以用int来表示。在涉及到二进制传输、读写文件的结构描述时,为了保持文件的结构不会受到不同编译目标平台字节长度的影响,不要使用intuint

数字字面量语法

  • Go1.13版本之后引入了数字字面量语法,这样便于开发者以二进制、八进制或十六进制浮点数的格式定义数字

  • v := 0b00101101, 代表二进制的 101101,相当于十进制的 45。 v := 0o377,代表八进制的 377,相当于十进制的 255。 v := 0x1p-2,代表十六进制的 1 除以 2²,也就是 0.25。

  • 而且还允许我们用 _ 来分隔数字,比如说: v := 123_456 表示 v 的值等于 123456。

    package main
    
    import "fmt"
    
    func main() {
    	// 十进制
    	var a int = 10
    	fmt.Printf("%d \n",a)	// 占位符%d表示10进制:10
    	fmt.Printf("%b \n",a)	// 占位符%b表示2进制:1010
    
    	// 八进制  以0开头
    	var b int = 077
    	fmt.Printf("%o \n",b)	// 77
    
    	// 十六进制  以0x开头
    	var c int = 0xff
    	fmt.Printf("%x \n",c)   	// ff
    	fmt.Printf("%X \n",c)  	// FF
    
    	// 变量的内存地址
    	fmt.Printf("%p \n", &a) // 占位符%p表示十六进制的内存地址:0xc00009c058 
    }
    

浮点类型

  • Go语言支持两种浮点型数:float32float64。这两种浮点型数据格式遵循IEEE 754标准: float32 的浮点数的最大范围约为 3.4e38,可以使用常量定义:math.MaxFloat32float64 的浮点数的最大范围约为 1.8e308,可以使用一个常量定义:math.MaxFloat64

    打印浮点数时,可以使用fmt包配合动词%f,代码如下:

    package main
    import (
            "fmt"
            "math"	// 导入多个包
    )
    func main() {
            fmt.Printf("%f\n", math.Pi)
            fmt.Printf("%.2f\n", math.Pi)
    }
    
  • 浮点型做运算:因为有IEEE784的标准,所有的浮点数运算都不精确

    • 转换成字符串去做运算
    • 整体放大多少倍去做运算

复数

  • complex64和complex128

  • 复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。

    var c1 complex64
    c1 = 1 + 2i
    var c2 complex128
    c2 = 2 + 3i
    fmt.Println(c1)  // 结果为(1+2i)
    fmt.Println(c2)  // 结果为(2+3i)
    

布尔值

  • Go语言中以bool类型进行声明布尔型数据,布尔型数据只有true(真)false(假)两个值。
  • 注意:
    1. 布尔类型变量的默认值为false
    2. Go 语言中不允许将整型强制转换为布尔型.
    3. 布尔型无法参与数值运算,也无法与其他类型进行转换。

字符串

  • Go 语言里的字符串的内部实现使用UTF-8编码。 字符串的值为双引号(")中的内容,可以在Go语言的源码中直接添加非ASCII码字符,例如:
s1 := "hello"
s2 := "你好"

字符串转义符

  • Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示。

    转义符 含义
    \r 回车符(返回行首)
    \n 换行符(直接跳到下一行的同列位置)
    \t 制表符
    \' 单引号
    \" 双引号
    \\ 反斜杠
  • 举个例子,我们要打印一个Windows平台下的一个文件路径:

    package main
    import (
        "fmt"
    )
    func main() {
    	fmt.Println("str := \"c:\\Code\\lesson1\\go.exe\"")
    	// 结果是str := "c:\Code\lesson1\go.exe"
    }
    

多行字符串

  • Go语言中要定义一个多行字符串时,就必须使用反引号字符:

  • 反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。

    s1 := `第一行
    第二行
    第三行
    `
    fmt.Println(s1)
    

字符串常用操作

方法 介绍
len(str) 求长度
+或fmt.Sprintf 拼接字符串
strings.Split 分割
strings.contains 判断是否包含
strings.HasPrefix,strings.HasSuffix 前缀/后缀判断
strings.Index(),strings.LastIndex() 子串出现的位置
strings.Join(a[]string, sep string) join操作
package main

import (
	"fmt"
	"strings"
)

func main() {
	// 计算字符串长度
	s1:="golangisgood"
	fmt.Println(len(s1))	// 计算s1的字符串长度:12

	// 字符串拼接
	s2:="python"
	fmt.Println(s1+s2)	// 使用+号把字符串拼接:golangisgoodpython
	s3:= fmt.Sprintf("%s----%s",s1,s2)
	fmt.Println(s3)		// 使用Sprintf占位符拼接:golangisgood----python

	// 分割
	ret := strings.Split(s1,"is")
	fmt.Println(ret)	// 分割:[golang good]

	// 判断是否包含
	ret2 := strings.Contains(s1,"is")
	fmt.Println(ret2)	// true

	// 判断前缀和后缀
	ret3 := strings.HasPrefix(s1,"go")	// 判断go是否是s1的前缀:true
	ret4 := strings.HasSuffix(s1,"is")	// 判断is是否是s1的后缀:false
	fmt.Println(ret3,ret4)

	// 求子串的位置
	s4 := "applepen"
	fmt.Println(strings.Index(s4,"p"))	// 求第一个出现p的位置:1
	fmt.Println(strings.LastIndex(s4,"p"))// 求最后一个出现p的位置:5

	// join组合
	a1 := []string{"Python","PHP","JavaScript","Ruby","Golang"}
	fmt.Println(strings.Join(a1,"-"))  // 把所有字符串用——拼接在一起:Python-PHP-JavaScript-Ruby-Golang
}

byte和rune类型

  • 组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 字符用单引号(’)包裹起来

    var a := '中'
    var b := 'x'
    
  • Go 语言的字符有以下两种:

    1. uint8类型,或者叫 byte 型,代表了ASCII码的一个字符。
    2. rune类型,代表一个 UTF-8字符
  • 当需要处理中文、日文或者其他复合字符时,则需要用到rune类型。rune类型实际是一个int32

    func main() {
    	s1 := "Golang"
    	c1 := 'G'	// ASCII码下占一个字节(8位,8bit)
    	fmt.Println(s1,c1)	// Golang 71
    	s2 := "中国"
    	c2 := '中'	// UTF-8编码下一个中文占3个字节
    	fmt.Println(s2,c2)  // 中国 20013
    
    	s3 := "hello中国"
        fmt.Println(len(s3))	// 因为每个中文字符占3个字节,所以5+6=11,长度为11
    }
    
  • Go 使用了特殊的 rune 类型来处理 Unicode,让基于 Unicode 的文本处理更为方便,也可以使用 byte 型进行默认字符串处理,性能和扩展性都有照顾。

    func main() {
    	s := "hello沙河"
    	// 遍历每个字节,包括中文字节,会把中文字节拆分成3个字节
    	for i := 0; i < len(s); i++ { //byte
    		fmt.Printf("%v(%c) ", s[i], s[i])
    	}
    	fmt.Println()
    	// for range 循环,是按照rune类型去遍历的
    	for _, r := range s { //rune
    		fmt.Printf("%v(%c) ", r, r)
    	}
    	fmt.Println()
    }
    // 输出为:
    104(h) 101(e) 108(l) 108(l) 111(o) 230(æ) 178(²) 153(™) 230(æ) 178(²) 179(³) 
    104(h) 101(e) 108(l) 108(l) 111(o) 27801(沙) 27827(河) 
    

修改字符串

  • 要修改字符串,需要先将其转换成[]rune[]byte,完成后再转换为string。无论哪种转换,都会重新分配内存,并复制字节数组。

    func main() {
    	// 强制类型转换
    	s5 := "big"
        // 将字符串强制转换成字节数组类型
    	byterArray := []byte(s5)
    	fmt.Println(byterArray)	// [98 105 103]
    	byterArray[0] = 'p'
    	fmt.Println(byterArray)	// [112 105 103]
    	// 将字节数组强制转换成字符串类型
        s5 = string(byterArray)	
    	fmt.Println(s5)			// pig
    }
    
  • 示例:字符串反转

    // 方式一:
    func main() {
    	s1 := "hello"
    	byteArray :=[]byte(s1)
    	s2 := ""
    	for i :=len(byteArray)-1;i>=0;i--{
    		s2 += string(byteArray[i])
    	}
    	fmt.Println(s2)
    }
    
    // 方式二:
    func main() {
    	s1 := "hello"
    	byteArray :=[]byte(s1)
    	length := len(byteArray)-1
    	for i :=0;i<=length/2;i++{
    		byteArray[i],byteArray[length-i] = byteArray[length-i],byteArray[i]
    	}
    	fmt.Println(string(byteArray))
    }
    

if条件判断

  • Go语言中最常用的流程控制有iffor,而switchgoto主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。

if条件判断基本写法

  • Go语言中if条件判断的格式:

  • 注意:大括号必须跟if在同一行

    if 表达式1{
        执行语句1
    }else if 表达式2{
        执行语句2
    }else{
        执行语句3
    }
    

if条件判断特殊写法

  • if条件判断还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断

  • 此变量只在if作用域中生效,if语句执行完毕后回收内存

    func ifDemo(){
    	if score := 65;score >= 90{	
    		fmt.Println("A")
    	}else if score>=75{
    		fmt.Println("B")
    	}else {
    		fmt.Println("C")
    	}
    }
    

for循环

  • Go 语言中的所有循环类型均可以使用for关键字来完成。

  • for循环的基本格式:

  • 条件表达式返回true时循环体不停地进行循环,直到条件表达式返回false时自动退出循环。

    for 初始语句;条件表达式;结束语句{
        循环体语句
    }
    
    // 例1:
    func forDemo() {
    	for i := 0; i < 10; i++ {
    		fmt.Println(i)
    	}
    }
    // 例2:
    func forDemo1(){
        for num,i:= 10,1; i<10 && num<=18; i, num = i+1, num+1  {
    		fmt.Printf("%d * %d = %d\n", num, i, num*i)
    	}
    }
    
  • for循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如:

    func forDemo2() {
    	i := 0
    	for ; i < 10; i++ {
    		fmt.Println(i)
    	}
    }
    
  • for循环的初始语句和结束语句都可以省略

    func forDemo3() {
    	i := 0
    	for i < 10 {
    		fmt.Println(i)
    		i++
    	}
    }
    

    这种写法类似于其他编程语言中的while,在while后添加一个条件表达式,满足条件表达式时持续循环,否则结束循环。

无限循环

  • for循环可以通过breakgotoreturnpanic语句强制退出循环。

    for {
        循环体语句
    }
    

for range(键值循环)

  • Go语言中可以使用for range遍历数组、切片、字符串、map 及通道(channel)。 通过for range遍历的返回值有以下规律:
    • 数组、切片、字符串返回索引和值。

    • map返回键和值。

    • 通道(channel)只返回通道内的值。

      import "fmt"
      
      func switchDemo1() {
      	// 只是英文字符
      	s := "abc"
      	for i:=range s{
      		fmt.Printf("下标=%d,值=%c; ",i,s[i])
      	}
      	fmt.Println()
      	// 带中文字符的
      	z := "我爱你中国"
      	for i,c :=range z{
      		fmt.Printf("下标=%d, 值=%c; ",i,c)
      	}
      }
      
      func main() {
      	switchDemo1()
      }
      // 下标=0,值=a; 下标=1,值=b; 下标=2,值=c; 
      // 下标=0, 值=我; 下标=3, 值=爱; 下标=6, 值=你; 下标=9, 值=中; 下标=12, 值=国; 
      

switch case

  • 使用switch语句可方便地对大量的值进行条件判断。

  • Go语言规定每个switch只能有一个default分支。

    func switchDemo1() {
    	finger := 3		// 条件语句
    	switch finger {
    	case 1:
    		fmt.Println("大拇指")
    	case 2:
    		fmt.Println("食指")
    	case 3:
    		fmt.Println("中指")
    	case 4:
    		fmt.Println("无名指")
    	case 5:
    		fmt.Println("小拇指")
    	default:
    		fmt.Println("无效的输入!")
    	}
    }
    
  • 一个分支可以有多个值,多个case值中间使用英文逗号隔开

    func testSwitch3() {
    	switch n := 7; n {
    	case 1, 3, 5, 7, 9:
    		fmt.Println("奇数")
    	case 2, 4, 6, 8:
    		fmt.Println("偶数")
    	default:
    		fmt.Println(n)
    	}
    }
    
  • 分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量

    func switchDemo4() {
    	age := 30
    	switch {
    	case age < 25:
    		fmt.Println("好好学习吧")
    	case age > 25 && age < 35:
    		fmt.Println("好好工作吧")
    	case age > 60:
    		fmt.Println("好好享受吧")
    	default:
    		fmt.Println("活着真好")
    	}
    }
    
  • fallthrough语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的

    func switchDemo5() {
    	s := "a"
    	switch {
    	case s == "a":			// 成立后
    		fmt.Println("a")
    		fallthrough			// 无条件的执行下一个case
    	case s == "b":
    		fmt.Println("b")
    	case s == "c":
    		fmt.Println("c")
    	default:
    		fmt.Println("...")
    	}
    }
    
    // 结果是a,b
    

break和continue

  • break:终止此次循环

  • break语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的forswitchselect的代码块上。

    func breakDemo1() {
    BREAKDEMO1:
    	for i := 0; i < 10; i++ {
    		for j := 0; j < 10; j++ {
    			if j == 2 {
    				break BREAKDEMO1	// break后面跟标签,可以终止标签中整个for循环
    			}
    			fmt.Printf("%v-%v\n", i, j)
    		}
    	}
    	fmt.Println("...")
    }
    
  • continue:跳过当次循环

  • continue语句后添加标签时,表示开始标签对应的循环。

    func continueDemo() {
    forloop1:
    	for i := 0; i < 5; i++ {
    		// forloop2:
    		for j := 0; j < 5; j++ {
    			if i == 2 && j == 2 {
    				continue forloop1	// 加上标签,可以控制从哪开始继续循环
    			}
    			fmt.Printf("%v-%v\n", i, j)
    		}
    	}
    }
    

goto跳转到指定位置

  • 可以跳转到指定位置

    func gotoDemo() {
    	for i := 0;i<5;i++{
    		goto LABEL
    		fmt.Println("for循环内")
    	}
    	fmt.Println("for循环外")
    	LABEL:
    		fmt.Println("跳转到goto执行语句中")
    }
    // 结果是  "跳转到goto执行语句中"
    
posted @ 2020-01-14 13:10  薛定谔的猫儿  阅读(175)  评论(0编辑  收藏  举报