Go语言基础——02 数据类型、运算符、控制结构

Go语言基础——02 数据类型、运算符、控制结构

数据类型

  • 基本数据类型
    • 布尔类型
    • 数字类型
      • 整型
      • 浮点型
    • 字符串类型
  • 派生数据类型
    • 指针
    • 数组
    • 结构体
    • 通道(channel)
    • 切片(slice)
    • 函数
    • 接口(interface)
    • Map

布尔类型

bool 型的值只能是常量:true 和 false。
两个相同类型的值可以通过运算符来进行比较,获得一个布尔型的值。

package main

import "fmt"

func main() {
	var a bool = true
	var b bool = false
	fmt.Println(a, b) // true false

	var c int = 10
	fmt.Println(c < 5) // false
}

数字类型

整型
  • 无符号整数
    • uint8(0 —> 255)
    • uint16(0 —> 65535)
    • uint32(0 —> 4294967295)
    • uint64(0 —> 18446744073709551615)
  • 整数
    • int8(-128 —> 127)
    • int16(-32768 —> 32768 )
    • int32(-2147483648 —> 2147483647)
    • int64(-9223372036854775808 —> 9223372036854775807)
浮点型
  • float32(IEEE-754 32位浮点型数;± 1e-45 —> ± 3.4 * 1e38)
  • float64(IEEE-754 64位浮点型数;± 5 1e-324 —> 107 1e308)
  • complex64(32位实数和虚数)
  • complex128(64位实数和虚数)
其它数字类型
  • byte(类似 uint8)
  • rune(类似 int32)
  • uint(32 或 64位)
  • int(与 uint 一样大小)
  • uintptr(无符号整型,用于存放一个指针)
package main

import "fmt"

func main() {
	var a int32
	var b int64
	a = 15
	//b = a + b // 编译错误 Cannot use 'a + b' (type int32) as the type int64
	b = b + 5 // 5
	fmt.Println(a, b)

	//var c int8 = 128 // 编译错误 128' (type untyped int) cannot be represented by the type int8
	//var d uint8 = -1 // 编译错误 The value of '-1' (type untyped int) cannot be represented by the type uint8
	var e float32 = 1.22323323
	fmt.Println(e) // 1.2232332
	var f float64 = 1.223233231231234
	fmt.Println(f) // 1.223233231231234
	fmt.Printf("f=%.2f\n", f) // f=1.22
	var g complex64 = complex(1, 2)
	fmt.Println(g) // (1+2i)

	fmt.Println(077)  // 63
	fmt.Println(0xFF) // 255
	fmt.Println(1e3)  //1000

	// 类型转换
	j := int64(a)
	fmt.Printf("j=%d, j的类型:%T\n", j, j) // j=15, j的类型:int64
}

注意:

  • 整型的零值为 0,浮点型的零值为 0.0。
  • int 型是计算最快的一种类型。
  • float32 精确到小数点后7位,float64 精确到小数点后15位。
  • 可以通过增加前缀 0 来表示 8 进制数(如:077),增加前缀 0x 来表示16 进制数(如:0xFF),使用 e 来表示 10 的连乘(如:1e3 = 1000,或 6.022e23 = 6.022 x 1e23)。

字符串类型

字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。

编码表

UTF-8编码:目前兼容我们绝大部分的文字和符号。
GBK编码:中国的编码表,号称兼容所有的中文汉字。
Unicode编码表:号称兼容了全世界的文字。

package main

import "fmt"

func main() {
	var str string = "这是一个字符串"
	fmt.Printf("str的类型:%T,str=%s\n", str, str) // str的类型:string,str=这是一个字符串

	str1 := 'A'
	str2 := "A"
	fmt.Printf("str1的类型:%T,str1=%d\n", str1, str1) // str1的类型:int32,str1=65
	fmt.Printf("str2的类型:%T,str2=%s\n", str2, str2) // str2的类型:string,str2=A

	str3 := '你'
	fmt.Printf("str3的类型:%T,str3=%d\n", str3, str3) // str3的类型:int32,str3=20320
}
  • Go语言中,所有的字符串都是由 单个字符 连接起来的
  • 单引号表示字符,双引号表示字符串(string)类型
  • 字符的本质是整型

转义字符

转义字符,所有的ASCII码都可以用"\"+数字(一般是8进制数字)来表示。

	/*
		换行
		你
		好
	*/
	fmt.Println("你\n好")

	/*
		删除上一个字符
		好
	*/
	fmt.Println("你\b好")

	/*
		tab
		你	好
	*/
	fmt.Println("你\t好")

数据类型转换

  • 在必要且可行的情况下,一个类型的值可以被转换为另一个类型的值。
  • Go语言中不存在隐式类型转换。所有的类型转换都必须显示的声明:新类型的值 = 新类型(旧类型的值)
package main

import "fmt"

func main() {
	var a float64 = 2.32
	var b int
	b = int(a)
	fmt.Printf("%T, %.2f\n", a, a) // float64, 2.32
	fmt.Printf("%T, %d\n", b, b)   // int, 2

	var c int = 12
	var d float64
	d = float64(c)
	fmt.Printf("%T, %d\n", c, c)   // int, 12
	fmt.Printf("%T, %.2f\n", d, d) // float64, 12.00

	//var e bool = true
	//var f int64
	// 编译错误 Cannot convert an expression of the type 'bool' to the type 'int64'
	//f = int64(e)
}

注意:

  • 布尔类型不支持类型转换
  • 浮点数转整数,会被截断,只保留整数部分

Go语言运算符

运算符用于执行程序代码运算。
Go语言内置的运算符有:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 其他运算符

每个运算符都有它们的优先级,计算机根据其优先级的不同,计算顺序也有所不同。
以下列出所有运算符以及它们的优先级,由上至下代表优先级由高到低:

优先级	运算符
7		^ !
6		* / % << >> & &^
5		+ - | ^
4		== != < <= >= >
3		<-
2		&&
1		||

注意:可以通过括号来临时提升某个表达式的整体运算优先级

算术运算符

运算符	描述
+		相加
-		相减
*		相乘
/		相除
%		求余
++		自增
--		自减
package main

import "fmt"

func main() {
	var a int = 10
	var b int = 20
	// 相加:10 + 20 = 30
	fmt.Printf("%d + %d = %d\n", a, b, a+b)
	// 相减:10 - 20 = -10
	fmt.Printf("%d - %d = %d\n", a, b, a-b)
	// 相乘:10 * 20 = 200
	fmt.Printf("%d * %d = %d\n", a, b, a*b)
	// 相除:20 / 10 = 2
	fmt.Printf("%d / %d = %d\n", b, a, b/a)
	// 求余:20 % 10 = 0
	fmt.Printf("%d %% %d = %d\n", b, a, b%a)
	// 自增:a++ = 11
	a++
	fmt.Printf("a++ = %d\n", a)
	// 自减:a-- = 10
	a--
	fmt.Printf("a-- = %d\n", a)
}

关系运算符

运算符	描述
==		检查两个值是否相等,如果相等返回 true 否则返回 false
!=		检查两个值是否不相等,如果不相等返回 true 否则返回 false
>		检查左边的值是否大于右边的值,如果是返回 true 否则返回 false
<		检查左边的值是否小于右边的值,如果是返回 true 否则返回 false
>=		检查左边的值是否大于等于右边的值,如果是返回 true 否则返回 false
<=		检查左边的值是否小于等于右边的值,如果是返回 true 否则返回 false
package main

import "fmt"

func main() {
	var a int = 10
	var b int = 20

	// ==:false
	fmt.Println(a == b)
	// !=:true
	fmt.Println(a != b)
	// >:false
	fmt.Println(a > b)
	// <:true
	fmt.Println(a < b)
	// >=:false
	fmt.Println(a >= b)
	// <=:true
	fmt.Println(a <= b)
}

逻辑运算符

运算符	描述
&&		逻辑与(和)AND,只要有一个为false,则为false;都为true,才为true
||		逻辑或(or)OR,只要有一个为true,则为true;都为false,才为false
!		取反,如果是真,则为假;如果是假,则为真
package main

import "fmt"

func main() {
	var a bool = true
	var b bool = false
	var c bool = true
	var d bool = false

	// &&:如果都为真,则为真;否则为假
	fmt.Println(a && b) // true && false = false
	fmt.Println(a && c) // true && true = true
	fmt.Println(b && d) // false && false = false

	// ||:如果其中一个为真,则为真;否则为假
	fmt.Println(a || b) // true && false = true
	fmt.Println(a || c) // true && true = true
	fmt.Println(b || d) // false && false = false

	// !:如果是真,则为假;否则为真
	fmt.Println(!a) // !true = false
	fmt.Println(!b) // !false = true
}

位运算符

运算符	描述
&		按位与(&),参与运算的两数各对应的二进位相与。都是1 结果为 1,否则为 0|		按位或(|),参与运算的两数各对应的二进位相或。是0 结果为 0,否则为 1^		按位异或(^),参与运算的两数各对应的二进位相异或。不同则为 1,相同为 0&^		位清空(&^),将指定位置上的值设置为 0。a &^ b,对于b上的每个数值,如果为 0,则取 a 对应位上的数值,如果为1,则取 0<<		左移(<<),左移n位就是乘以2的n次方。其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0>>		右移(>>),右移n位就是除以2的n次方。其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。
package main

import "fmt"

func main() {
	var a int = 30
	var b int = 15
	// a的二进制为:11110,b的二进制为:1111
	fmt.Printf("a=%d, 其二进制值为: %b\n", a, a)
	fmt.Printf("b=%d, 其二进制值为: %b\n", b, b)

	// &: 都是1 结果为 1,否则为 0。
	/*
		0001 1110
		&
		0000 1111
		——————————
		0000 1110
	*/
	// 30 & 15 = 14, 11110 & 1111 = 1110
	fmt.Printf("%d & %d = %d, %b & %b = %b\n", a, b, a&b, a, b, a&b)

	// |: 都是0 结果为 0,否则为 1。
	/*
		0001 1110
		|
		0000 1111
		——————————
		0001 1111
	*/
	// 30 | 15 = 31, 11110 | 1111 = 11111
	fmt.Printf("%d | %d = %d, %b | %b = %b\n", a, b, a|b, a, b, a|b)

	// ^: 不同则为 1,相同为 0。
	/*
		0001 1110
		^
		0000 1111
		——————————
		0001 0001
	*/
	// 30 ^ 15 = 17, 11110 ^ 1111 = 10001
	fmt.Printf("%d ^ %d = %d, %b ^ %b = %b\n", a, b, a^b, a, b, a^b)

	// &^: 对于b上的每个数值,如果为 0,则取 a 对应位上的数值,如果为1,则取 0。
	/*
		0001 1110
		&^
		0000 1111
		——————————
		0001 0000
	*/
	// 30 &^ 15 = 16, 11110 &^ 1111 = 10000
	fmt.Printf("%d &^ %d = %d, %b &^ %b = %b\n", a, b, a&^b, a, b, a&^b)

	// <<: 把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。
	/*
		0001 1110 << 2
		——————————————
		0111 1000
	*/
	// 30 << 2 = 120, 11110 << 2 = 1111000
	fmt.Printf("%d << 2 = %d, %b << 2 = %b\n", a, a<<2, a, a<<2)

	// >>: 把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。
	/*
		0001 1110 >> 2
		——————————————
		0000 0111
	*/
	// 30 >> 2 = 7, 11110 >> 2 = 111
	fmt.Printf("%d >> 2 = %d, %b >> 2 = %b\n", a, a>>2, a, a>>2)
}

赋值运算符

运算符	描述
=		简单的赋值运算符,将一个表达式的值赋给一个左值,C = A + B,将 (A + B) 这个表达式的值赋值给 C
+=		相加后再赋值,C += A 等于 C = C + A
-=		相减后再赋值,C -= A 等于 C = C - A
*=		相乘后再赋值,C *= A 等于 C = C * A
/=		相除后再赋值,C /= A 等于 C = C / A
%=		求余后再赋值,C %= A 等于 C = C % A
<<=		左移后再赋值,C <<= 2 等于 C <<= C << 2
>>=		右移后再赋值,C >>= 2 等于 C >>= C >> 2
&=		按位与后再赋值,C &= 2 等于 C &= C & 2
|=		按位或后再赋值,C |= 2 等于 C |= C | 2
^=		按位异或后再赋值,C ^= 2 等于 C ^= C ^ 2
package main

import "fmt"

func main() {
	var a int = 30
	var b int = 15
	var c int

	// c = 30 + 15, c的值为: 45
	fmt.Printf("c = %d + %d, c的值为: %d\n", a, b, a+b)

	// c += 30, c的值为: 40
	c = 10
	c += a
	fmt.Printf("c += %d, c的值为: %d\n", a, c)

	// c -= 30, c的值为: -20
	c = 10
	c -= a
	fmt.Printf("c -= %d, c的值为: %d\n", a, c)

	// c *= 30, c的值为: 300
	c = 10
	c *= a
	fmt.Printf("c *= %d, c的值为: %d\n", a, c)

	// c /= 30, c的值为: 0
	c = 10
	c /= a
	fmt.Printf("c /= %d, c的值为: %d\n", a, c)

	// c %= 30, c的值为: 10
	c = 10
	c %= a
	fmt.Printf("c %%= %d, c的值为: %d\n", a, c)

	// c的二进制值为: 1010, c <<= 2, c的值为: 40, c的二进制值为: 101000
	c = 10
	fmt.Printf("c的二进制值为: %b, ", c)
	c <<= 2
	/*
		0000 1010 << 2
		———————————————
		0010 1000
	*/
	fmt.Printf("c <<= 2, c的值为: %d, c的二进制值为: %b\n", c, c)

	// c的二进制值为: 1010, c >>= 2, c的值为: 2, c的二进制值为: 10
	c = 10
	fmt.Printf("c的二进制值为: %b, ", c)
	c >>= 2
	/*
		0000 1010 >> 2
		———————————————
		0000 0010
	*/
	fmt.Printf("c >>= 2, c的值为: %d, c的二进制值为: %b\n", c, c)

	// c的二进制值为: 1010, 2的二进制值为: 10, c &= 2, c的值为: 2, c的二进制值为: 10
	c = 10
	fmt.Printf("c的二进制值为: %b, 2的二进制值为: %b, ", c, 2)
	c &= 2
	/*
		0000 1010
		&
		0000 0010
		———————————————
		0000 0010
	*/
	fmt.Printf("c &= 2, c的值为: %d, c的二进制值为: %b\n", c, c)

	// c的二进制值为: 1010, 2的二进制值为: 10, c |= 2, c的值为: 10, c的二进制值为: 1010
	c = 10
	fmt.Printf("c的二进制值为: %b, 2的二进制值为: %b, ", c, 2)
	c |= 2
	/*
		0000 1010
		|
		0000 0010
		———————————————
		0000 1010
	*/
	fmt.Printf("c |= 2, c的值为: %d, c的二进制值为: %b\n", c, c)

	// c的二进制值为: 1010, 2的二进制值为: 10, c ^= 2, c的值为: 8, c的二进制值为: 1000
	c = 10
	fmt.Printf("c的二进制值为: %b, 2的二进制值为: %b, ", c, 2)
	c ^= 2
	/*
		0000 1010
		^
		0000 0010
		———————————————
		0000 1000
	*/
	fmt.Printf("c ^= 2, c的值为: %d, c的二进制值为: %b\n", c, c)
}

其他运算符

运算符	描述
&		返回变量存储地址;&a;将给出变量的实际地址
*		指针变量;*a;是一个指针变量
package main

import "fmt"

func main() {
	var a string = "hello"
	// &a的类型: *string, a的内存地址: 0xc00004e250
	fmt.Printf("&a的类型: %T, a的内存地址: %v\n", &a, &a)

	var ptr *string
	ptr = &a
	// *ptr的类型: string, *ptr为: hello
	fmt.Printf("*ptr的类型: %T, *ptr为: %v\n", *ptr, *ptr)
}

类型别名

package main

import "fmt"

type newInt int

func main() {
	var a, b newInt = 1, 2
	c := a + b
	// c 的类型: main.newInt, c 的值: 3
	fmt.Printf("c 的类型: %T, c 的值: %d", c, c)

	//var d int = 3
	// 编译错误 Invalid operation: a+d (mismatched types newInt and int)
	//e := a+d
}
  • 在代码中,我们可以给某个类型重新定义一个名字。(用于简化名称或解决名称冲突)
  • 类型别名定义格式:type 新名字 类型
  • 类型别名得到的新类型并非与原类型完全相同,新类型不会拥有原类型所附带的方法。

Go语言中的控制结构

在Go语言中程序有几种执行代码的结构:

  • 顺序结构:自上而下执行
  • 选择结构:满足一定条件才会执行
  • 循环结构:条件满足的情况下,会去循环执行 0~N 次

在前面,所了解到的Go程序,都是从 main() 函数开始执行,然后按顺序执行该函数体中的代码。但是在实际的编程中,我们经常会需要对一些特殊情况进行判断,并在满足一些特定条件的情况下才执行某些代码,也就是在代码中进行条件判断。
在Go语言中提供了以下几种条件判断语句:

  • if 语句
  • if...else... 语句
  • if 嵌套语句
  • switch 语句
  • select 语句
    注意:Go语言中没有三目运算符,所以不支持 ?: 形式的条件判断

if

  • if 条件:bool{} ,可以单独存在
  • if 条件:bool{}...else...
  • if 条件:bool{}...else if 条件:bool{}...else if 条件:bool{}...else
package main

import "fmt"

func main() {
	var a int = 10
	var b int = 20

	if a < b {
		fmt.Println("a的值比b的值大")
	}

	if a > b {
		fmt.Println("a的值比b的值大")
	} else {
		fmt.Println("a的值比b的值小")
	}
}
package main

import "fmt"

func main() {
	for {
		var username string
		var pwd string
		fmt.Println("请输入账号:")
		fmt.Scan(&username)
		fmt.Println("请输入密码:")
		fmt.Scan(&pwd)
		if username == "root" && pwd == "123" {
			fmt.Println("[管理员] 登录成功!")
		} else if username == "user1" && pwd == "123" {
			fmt.Println("[user1] 登录成功!")
		} else {
			fmt.Println("登录失败!")
		}
	}
}

switch

switch的使用
  • switch - case
  • switch - case - fallthrough
  • switch - case - default
package main

import "fmt"

func main() {
	var name string

	for {
		fmt.Println("请输入您的名字:")
		fmt.Scan(&name)
		switch name {
		case "user1":
			fmt.Println("user1")
		case "user2":
			fmt.Println("user2")
		default:
			fmt.Println("名字不存在")
		}
	}
}
package main

import "fmt"

func main() {
	var name string

	for {
		fmt.Println("请输入您的名字:")
		fmt.Scan(&name)
		// switch可以省略条件,默认是 switch true
		switch {
		case name == "user1":
			fmt.Println("user1")
		case name == "user2":
			fmt.Println("user2")
		default:
			fmt.Println("名字不存在")
		}
	}
}
case穿透:fallthrough
package main

import "fmt"

func main() {
	boolean := 1

	/*
		输出:
			case1
			case2
	*/
	switch boolean {
	case 1:
		fmt.Println("case1")
		// 在 case 中,一旦使用了 fallthrough,则会强制执行下一个 case 语句
		fallthrough
	case 2:
		fmt.Println("case2")
		// break 可以跳出并终止这个 case,也可以退出 case 穿透
		break
		fallthrough
	case 3:
		fmt.Println("case3")
	default:
		fmt.Println("default")
	}
}

select

  • select 只能用于通道的读写操作
  • select 中的case条件(非阻塞)是并发执行的,select会选择先操作成功的那个case条件去执行,如果多个同时返回,则随机选择一个执行,此时将无法保证执行顺序。对于阻塞的 case 语句会直到其中有信道可以操作;如果有多个信道可操作,会随机选择其中一个 case 执行。

for

在Go语言中,如果想要重复执行某些语句,则只有使用 for 结构。

基于计数器的迭代

基本形式:
for 初始化语句; 条件语句; 修饰语句(自增或自减) {}

package main

import "fmt"

func main() {
	// 循环打印 5次 hello
	for i := 0; i < 5; i++ {
		fmt.Println("hello, 打印次数:", i)
	}
}
基于条件判断的迭代

基本形式:
for 条件语句 {}

package main

import "fmt"

func main() {
	var i int = 5
	for i >= 0 {
		fmt.Println("i=", i)
		i -= 1
	}
}
无限循环

基本形式:
for {}
for循环中,如果头部没有条件语句,则会认为条件永远为 true,因此循环体内必须有相关的条件判断以确保会在某个时刻退出循环。

package main

import "fmt"

func main() {
	var a int
	for {
		fmt.Println("请输入一个数字:")
		fmt.Scan(&a)
		fmt.Println("输入了一个:", a)
	}
}
for-rang 结构

基本形式:
for 下标, 值 := range coll {}

package main

import "fmt"

func main() {
	var nums = [4]int{1, 2, 3, 4}
	/*
		0 1
		1 2
		2 3
		3 4
	*/
	for i, i1 := range nums {
		fmt.Println(i, i1)
	}
}
for 终止循环
  • break:结束整个循环,立即停止。
  • continue:结束当前这次循环,继续执行下一次循环。
  • goto:将控制转移到被标记的语句。
package main

import "fmt"

func main() {
	/*
		0
		1
	*/
	for i := 0; i < 5; i++ {
		if i == 2 {
			break
		}
		fmt.Println(i)
	}
}
package main

import "fmt"

func main() {
	/*
		0
		1
		3
		4
	*/
	for i := 0; i < 5; i++ {
		if i == 2 {
			continue
		}
		fmt.Println(i)
	}
}
package main

import "fmt"

func main() {
	var a int = 10

	/*
		a的值为:10
		a的值为:11
		a的值为:12
		a的值为:13
		a的值为:14
		a的值为:16
		a的值为:17
		a的值为:18
		a的值为:19
	*/
LOOP:
	for a < 20 {
		if a == 15 {
			a = a + 1
			// 在变量a等于15的时候跳过本次循环并回到循环的开始语句 LOOP 处
			goto LOOP
		}
		fmt.Printf("a的值为:%d\n", a)
		a++
	}
}
嵌套for循环

使用for循环打印 九九乘法表

package main

import "fmt"

func main() {
	for i := 1; i <= 9; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%d * %d = %d \t", j, i, i*j)
		}
		fmt.Println()
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值