Go入门介绍

Golang特点

Go语言既能达到静态语言的安全和性能,又达到了动态语言开发维护的高效,使用一个表达式来形容Go语音(Go = C + Python),说明Go语言既有C静态语言程序的运行速度,又能达到Python动态语言的快速开发。
1、go从C语言中继承了很多理念,包括表达式语法、控制结构、基础数据类型、调用参数传值、指针(弱化指针)等,也保留了和C语言一样的编译执行方式。
2、函数可以返回多个值
3、引入包的概念,用于组织程序结构,Go语言的一个文件都要归属于一个包,而不能单独存在。
4、垃圾回收机制,内存自动回收,不需要开发人员管理。
5、天然并发

  • 从语言层面支持并发,实现简单
  • goroutine,轻量级线程,可实现大并发处理,高效利用多核
  • 基于CPS并发模型实现

6、吸收了管道通信机制,形成Go语言特有的channel,通过管道channel,可以实现不同的goroute之间的相互通信
7、新的创新,比如切片slice,延时执行defer等

Golang操作(入门级)

1、GO程序执行
		go build go1.go --> go1.exe通过go build生成可执行文件.exe,然后执行可执行文件即可
		go run go1.go 通过go run 直接执行,需要电脑有go的环境,不会生成其他文件
2、Go语法要求
		每条语句不需要分号结尾,因此,一行也只能有一条语句
		导入的包或者是定义的变量如果没有使用到会报错,无法通过编译( 如果没有使用fmt中的函数--> imported and not used: "fmt")
		缩进是一次tab键,没有缩进不会出现语法错误,仅是格式不对
		注释和c语言一样
		函数左侧花括号不能独立一行,否则会报错。只能是和函数名同一行,然后换行写语句。
			# command-line-arguments
			.\go1.go:19:1: syntax error: unexpected semicolon or newline before {
3、格式化代码
		gofmt go1.go 可以将该文件中的代码格式化之后输出到控制台
		gofmt -w go1.to 可以将文件中的代码格式化之后写入到文件中

Golang变量

1、变量使用步骤

变量使用步骤
		声明变量(定义变量)
			基本语法:var 变量名 数据类型
			比如,var a int声明一个int类型的变量a
			
		初始化变量
			在声明变量的时候就赋值
			var a int = 90 这就是初始化变量a。
			细节:如果声明的时候就直接赋值,可以省略数据类型(自动推导类型)
				var b = 99
				
		变量赋值
			如果只是声明了变量:var num int //默认值为0
			然后再给值num = 99这就是赋值。

2、局部变量的使用方式

第一种:指定变量类型,声明后若不赋值,使用默认值

package main
import "fmt"

func main() {
	//这种方式相当于直接使用定义了一个变量,使用他的默认值
	var i int
	fmt.Println("i = ", i)

	var f float64
	fmt.Println("f = ", f)

	var s string
	fmt.Println("s = ", s, "s ==\"\" ?", s == "")
}

第二种:根据值自行判定变量类型(类型推导)
这种方式下必须在定义的时候赋值,不能后期赋值。这种方式也不存在默认值一说,因为一开始就要手动赋值,否则会报错。

package main
import "fmt"

func main() {

	var i = 98
	fmt.Println("i = ", i)

	var s = "你好"
	fmt.Println("s = ", s)

}

错误情况
在这里插入图片描述
第三种:省略 var, 注意 :=左侧的变量不能是已经声明过的,否则会导致编译错误。
这种方式既然省略了var关键字,就不能再使用它,否则会报错。

package main
import "fmt"

func main() {

	//相当于 var name string 	name= "kiko"
	name := "kiko"
	fmt.Println("name: ", name)

}
var + 变量名 + 数据类型:=var和数据类型两者的共同点就是必须要赋初值
声明多个变量
package main
import "fmt"

func main() {

	//多变量声明方式1(基本形式,只能是一种类型)
	var n1, n2, n3 int	
	n1 = 99
	fmt.Println("n1 = ", n1, "n2 = ", n2, "n3 = ", n3)	//n1 =  99 n2 =  0 n3 =  0

	//多变量声明方式2(省略数据类型)
	var n4, psw, distance = 190, "admin", 99.99
	fmt.Println("n4 =", n4, "psw =", psw, "distance =", distance) //n4 = 190 psw = admin distance = 99.99

	//多变量声明方式3(省略var)
	n5, n6, n7 := 999, 99.99, "vovo"
	fmt.Println("n5 =", n5, "n6 =", n6, "vovo =", n7)
}

3、全局变量的使用方式

全局变量和局部变量的使用方式基本相同,前两种方式是一样的,但是全局变量没有 := 定义的方式,此外全局变量可以定义在一起,共用一个var关键字。
全局变量在使用过程中通常都是设置了一个初始值,一般不会只声明全局变量。

package main
import "fmt"

func main() {

	//输出全局变量
	fmt.Println("gn1 = ", gn1, "gn2 =", gn2, "gn3 =", gn3, "gn4 =", gn4, "gn5 =", gn5, "gn6 =", gn6)
	
}

/*
	全局变量可以定义在使用了全局变量函数的后面
*/

//定义全局变量
var gn1 = 100
var gn2 = 888.888
var gn3 = "yoyo"

//上面的声明方式可以改成一次性声明
var (
	gn4 = 500
	gn5 = 999.999
	gn6 = "kiko"
)

4、变量使用的注意事项

  • 变量 = 变量名 + 数据类型 + 数值缺一不可。
  • Golang的变量如果没有赋初值,编译器会使用默认值,比如 int 默认值 0 ,string 默认值为空串,即"",小数默认为 0。
  • 变量在同一个作用域(在一个函数或者在代码块)内不能重名。

5、程序中的+号

  • 当左右两边都是数值型时,则做加法运算
  • 当左右两边都是字符串,则做字符串拼接
package main
import "fmt"

func main() {

	//数值类型的 + 
	var i = 10
	// var f = 19.9	//这里测试要注释掉,因为没有使用到f这个变量,否则编译出错
	var i1 = 20
	//两种不同的数值类型不能做 加法运算,这里的i + f是无法通过编译的
	var res1 = i + i1
	fmt.Println(" i + f = ", res1,)

	//字符串
	name := "kiko"
	friend := "yoyo"
	res2 := name + friend
	fmt.Println("name + friend = ", res2)

}

Golang数据类型(基本类型)

1、数据类型分类

在这里插入图片描述

2、整型

第一种、有符号整数
在这里插入图片描述
第二种、无符号整数
在这里插入图片描述
第三种、其他整数类型
在这里插入图片描述
使用对应的类型,数值就不能超过类型限定的值,否则无法编译通过。

使用细节
  • Golang 各整数类型分:有符号和无符号,int uint 的大小和系统有关。
  • Golang 的整型默认声明为 int 型,就是自动推导的类型。
    在这里插入图片描述
  • 查看变量类型和所占子节大小
    在这里插入图片描述
  • Golang 程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型。【如:年龄,使用byte类型就足够了】
  • bit: 计算机中的最小存储单位。byte:计算机中基本存储单元。

3、小数类型/浮点型

  1. 类型分类(都是有符号的)
    在这里插入图片描述
package main
import (
	"fmt"
	"unsafe"
)

func main(){
	
	var f float32 = 10.2000001
	fmt.Println("f = ", f)
	fmt.Printf("type = %T, size = %d\n", f, unsafe.Sizeof(f))

	var d = 123.898323212	//默认自动推导到float64
	fmt.Println("d = ", d)
	fmt.Printf("type = %T, size = %d\n", d, unsafe.Sizeof(d))
}
浮点数=符号位+指数位+尾数位
Golang 浮点类型有固定的范围和字段长度,不受具体OS(操作系统)的影响。
Golang 的浮点型默认声明为 float64 类型。
浮点型常量有两种表示形式:
	十进制数形式:如:5.12 .512 (必须有小数点)
	科学计数法形式:如:5.1234e2 = 5.1234 * 10 的 2 次方 5.12E-2 = 5.12/10 的 负2次方
通常情况下,应该使用 float64 ,因为它比 float32 更精确。[开发中,推荐使用 float64]
package main
import (
	"fmt"
	"unsafe"
)

func main() {

	//十进制形式:如 5.12   .512(必须有小数点)
	num1 := 5.12
	num2 := .512
	fmt.Println("num1: ", num1, " num2: ", num2)
	fmt.Printf("num1 type %T: num1 size %d\n", num1, unsafe.Sizeof(num1))

	//科学计数法形式
	num3 := 5.1234e2
	num4 := 5.1234E2
	num5 := 5.1234E-2
	fmt.Println("num3: ", num3, " num4: ", num4, " num5: ", num5)
	fmt.Printf("num3 type %T: num3 size %d\n", num3, unsafe.Sizeof(num3))

}

在这里插入图片描述

4、字符类型

byteGo 的字符串不同,它是由字节组成的
package main
import(
	"fmt"
)

func main() {

	var c byte = 'a'
	var z byte = '0'

	//直接输出变量是输出字符对应的码值
	fmt.Println("c = ", c, " z = ", z)
	//使用格式化输出可以输出字符串
	fmt.Printf("c = %c, z = %c\n", c, z)

	// var x byte = '你'  //overflows byte
	var x int = '你'
	fmt.Println("x = ",	 x)

}

在这里插入图片描述
说明:
如果我们保存的字符在 ASCII 表的,比如[0-1, a-z,A-Z…]直接可以保存到 byte
如果我们保存的字符对应码值大于 255,这时我们可以考虑使用 int32(rune) 类型保存
如果我们需要安装字符的方式输出,这时我们需要格式化输出,即 fmt.Printf(“%c”, c1)…
在这里插入图片描述

var c1 byte = 'a' ; var c2 int = '中' ; var c3 byte = '9''\’var c3 char = ‘\n’UTF-8英文字母-1 个字节 汉字-3 个字节字符的本质是一个整数%crune
package main
import(
	"fmt"
)

func main() {

	// var x byte = '你'  //overflows byte
	var x int = '你'
	fmt.Println("x = ",	 x)

	//字符运算
	var ch byte = 'a'
	var chs = ch + 10
	fmt.Println("chs = ", chs)
	fmt.Printf("chs = %c\n", chs)

}
统一成了 utf-8

5、布尔类型

只允许取值true和false1个子节
package main
import(
	"fmt"
	"unsafe"
)

func main() {

	var b bool
	fmt.Println("b = ", b)		//默认值为false

	var b1 = true
	fmt.Println("b1 = ", b1)

	fmt.Printf("b type = %T, b size = %d\n", b, unsafe.Sizeof(b))

}

在这里插入图片描述

6、字符串类型

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

package main
import (
	"fmt"
	"unsafe"
)

func main(){
	name := "你好 Golang"
	fmt.Println(name)
	fmt.Printf("type = %T, size = %d\n", name, unsafe.Sizeof(name))
}

在这里插入图片描述

*** string 使用注意事项和细节
1、Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本,这样 Golang 统一使用 UTF-8 编码,中文乱码问题不会再困扰程序员。
2、字符串一旦赋值了,字符串就不能修改字符串内部的元素了;在 Go 中字符串是不可变的。但是可以重新整体赋值。
3、字符串的两种表示形式
第一、双引号, 会识别转义字符
第二、反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果

package main
import (
	"fmt"
	// "unsafe"
)

func main(){
	
	//双引号形式,可以识别转义字符\n
	name := "你好\nGolang"	
	fmt.Println(name)
	
	//使用反引号,按照字符串原样输出
	user := `		
	package main
	import (
		"fmt"
		"unsafe"
	)
	
	func main() {
	
		//十进制形式:如 5.12   .512(必须有小数点)
		num1 := 5.12
		num2 := .512
		fmt.Println("num1: ", num1, " num2: ", num2)
		fmt.Printf("num1 type %T: num1 size %d\n", num1, unsafe.Sizeof(num1))
	
		//科学计数法形式
		num3 := 5.1234e2
		num4 := 5.1234E2
		num5 := 5.1234E-2
		fmt.Println("num3: ", num3, " num4: ", num4, " num5: ", num5)
		fmt.Printf("num3 type %T: num3 size %d\n", num3, unsafe.Sizeof(num3))
	
	}
	`
	fmt.Println(user)
	
}

在这里插入图片描述
4、字符串拼接
字符串拼接使用+号,如果一行字符串太长可以换行拼接。

package main
import (
	"fmt"
)

func main(){
	
	str := "hello world" + " HELLO Golang"
	fmt.Println(str)

	//分行连接, +号必须在行尾,而不能是下一行开头
	nstr := "HELLO Golang" + " HELLO Go" +
	" fmt" + "YOYO" + 
	" MM"
	fmt.Println(nstr)
}

在这里插入图片描述

7、基本数据类型默认值

在这里插入图片描述
在这里插入图片描述

8、基本数据类型(数值)的相互转换

需要显式转换
T(v)
package main

import (
	"fmt"
	// "unsafe"
)

func main() {
	//T(v)
	var i int32 = 100
	//希望将 i ==> float
	var n1 float32 = float32(i)	
	var n2 int8 = int8(i)		//高精度转低精度
	var n3 int64 = int64(i)		//低精度转高精度

	fmt.Printf("i = %v, n1 = %v, n2 = %v, n3 = %v\n", i, n1, n2, n3)

}

在这里插入图片描述
*** 基本数据类型相互转换的注意事项
1、Go 中,数据类型的转换可以是从 范围小–>范围大,也可以 范围大—>范围小。
2、被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化!也就是不会影响被转换的变量的本身。
3、在转换中,比如将 int64 转成 int8 【-128—127】 ,编译时不会报错,只是转换的结果是按溢出处理,和我们希望的结果不一样(其他语言也是这么处理的)。 因此在转换时,需要考虑范围,这种情况只可能出现在高精度转低精度。

package main

import (
	"fmt"
	// "unsafe"
)

func main() {

	//T(v)
	var i int64 = 8888
	//希望将 int64 --> int8
	var n1 int8 = int8(i)		//高精度转低精度

	fmt.Printf("i = %v, n1 = %v\n", i, n1)

}

在这里插入图片描述
4、其他细节(关于不同类型计算)
不同类型之间无法计算,即使同为整型,因为具体的类型不一致也会报错。

package main

import (
	"fmt"
	// "unsafe"
)

func main() {

	var n1 int32 = 12
	var n2 int64
	var n3 int8

	//下面是错误写法(编译报错),类型是虽然都是整型,但是类型还是不一致的,必须完全一致才可以。返回的类型和计算的变量的类型必须一致,且计算的两个都是变量,这两个变量也必须类型一致。如果计算的都是常量,那么不会出现问题,返回值会自动匹配返回类型。
	// n2 = n1 + 20
	// n3 = n1 + 20

	//这种写法可以。常量20可以自动匹配类型,n1就要转换成和n2、n3一致的类型才可以计算
	n2 = int64(n1) + 20	
	n3 = int8(n1) + 20

	fmt.Println(n1, n2, n3)
}

两种执行情况
在这里插入图片描述

package main

import (
	"fmt"
	// "unsafe"
)

func main() {

	var n1 int32 = 12
	var n2 int8
	var n3 int8

	// int8类型最大值是127
	n2 = int8(n1) + 127	//编译通过,但是结果按照溢出处理
	// n3 = int8(n1) + 128	//编译无法通过,因为128和int8类型不匹配。
	
	fmt.Println(n1, n2, n3)
}

在这里插入图片描述

9、基本数据类型(数值)和string类型转换

*** 基本介绍
在实际开发过程中,通常需要将字符串转成基本数据类型,或者将基本数据类型的数值当成字符串处理。

基本类型转string类型
package main

import (
	"fmt"
)

func main() {

	//方式1、fmt.Sprintf("%参数", 表达式)
	var num1 int = 99
	var num2 float64 = 23.36989
	var b bool = true
	var ch byte = 'H'
	var str string

	str = fmt.Sprintf("%d", num1)
	fmt.Printf("str type %T str = %q\n", str, str)

	str = fmt.Sprintf("%f", num2)
	fmt.Printf("str type %T str = %q\n", str, str)

	str = fmt.Sprintf("%t", b)
	fmt.Printf("str type %T str = %q\n", str, str)

	str = fmt.Sprintf("%c", ch)
	fmt.Printf("str type %T str = %q\n", str, str)
}

在这里插入图片描述
2、方式二:使用时 strconv 包的函数
在这里插入图片描述

package main

import (
	"fmt"
	// "unsafe"
	"strconv"
)

func main() {

	//使用strconv包里的函数
	var num1 int = 99
	var num2 float64 = 12.3659
	var b2 bool = true

	//1、func FormatInt(int64, int) string --> 第一个参数必须是int64,第二个参数是进制
	str := strconv.FormatInt(int64(num1), 10)	//10进制
	fmt.Printf("str type %T str = %q\n", str, str) //%q表示输出的字符串会用""括起来

	str = strconv.FormatInt(int64(num1), 2)		//2进制
	fmt.Printf("str type %T str = %q\n", str, str)

	//2、func FormatFloat(float64, byte, prec, bitSize) string
	//第一个参数必须是要转换的浮点型,且是float64
	//第二个参数是格式,小数形式还是科学计数法形式;第三个参数表示小数点后保留位数
	//第四个参数表示这个小数是float64类型的
	str = strconv.FormatFloat(num2, 'f', 10, 64)
	fmt.Printf("str type %T str = %q\n", str, str)

	//3、func FormatBool(bool) string
	str = strconv.FormatBool(b2)
	fmt.Printf("str type %T str = %q\n", str, str)

	//4、func Itoa(i int) string
	//Itoa 内部直接调用 FormatInt(i, 10) 实现的
	var num5 int64 = 4567
	str = strconv.Itoa(int(num5))
	fmt.Printf("str type %T str = %q\n", str, str)

}

在这里插入图片描述

string类型转基本类型
package main

import (
	"fmt"
	// "unsafe"
	"strconv"
)

func main() {

	var str string = "true"
	var b bool

	//1. strconv.ParseBool(str)(bool, error)函数返回两个值,参数一个字符串
	//因为只要获取到bool value,不想获取error,所以可以使用 _ 忽略
	b, _ = strconv.ParseBool(str)
	fmt.Printf("b type %T, b = %v\n", b, b)

	//2. strconv.ParseInt(string, base int, bitSize int)(int64, error)
	var str2 string = "123456"
	var n1 int64
	var n2 int
	n1, _ = strconv.ParseInt(str2, 10, 64)
	n2 = int(n1)
	fmt.Printf("n1 type %T, n1 = %v\n", n1, n1)
	fmt.Printf("n2 type %T, n2 = %v\n", n2, n2)

	//3. strconv.ParseFloat(string, bitSize)(float64, error)
	var str3 string = "12.45"
	var f1 float64
	f1, _ = strconv.ParseFloat(str3, 64)
	fmt.Printf("f1 type %T, f1 = %v\n", f1, f1)
}
string 转基本数据类型的注意事项
package main

import (
	"fmt"
	"strconv"
)

func main() {

	var str string = "HELLO"
	var n int64 = 11

	n, _ = strconv.ParseInt(str, 10, 64)
	fmt.Printf("n type %T, n = %v\n", n, n)
}

在这里插入图片描述

10、指针类型

基本介绍&*
package main

import (
	"fmt"
	// "strconv"
)

func main() {

	var i int = 90
	fmt.Println("i变量的地址 ", &i)
	fmt.Println("i变量的值 = ", i)

	var ptr_i *int = &i
	fmt.Println("ptr_i = ", ptr_i)
	fmt.Println("ptr_i 指针指向的值= ", *ptr_i)

	*ptr_i = 100		//修改指向的值
	fmt.Println("i变量的地址 ", &i)
	fmt.Println("i变量的值 = ", i)
	fmt.Println("ptr_i = ", ptr_i)
	fmt.Println("ptr_i 指针指向的值= ", *ptr_i)
	
}
*数据类型int的对应的指针就是*int基本数据类型int系列,float系列,bool,string,数组和结构体struct

11、值类型和引用类型

值类型引用类型
使用特点栈堆

Golang中的标识符和占位符

1、标识符

概念
命名规则不能单独作为标识符使用
注意事项首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用

2、占位符(格式化输出)

*** 普通占位符

%v	the value in a default format
	when printing structs, the plus flag (%+v) adds field names
%#v	a Go-syntax representation of the value
%T	a Go-syntax representation of the type of the value
%%	a literal percent sign; consumes no value

*** 布尔类型

%t	the word true or false

*** 整型

%b	base 2
%c	the character represented by the corresponding Unicode code point
%d	base 10
%o	base 8
%O	base 8 with 0o prefix
%q	a single-quoted character literal safely escaped with Go syntax.
%x	base 16, with lower-case letters for a-f
%X	base 16, with upper-case letters for A-F
%U	Unicode format: U+1234; same as "U+%04X"

*** 浮点型

%b	decimalless scientific notation with exponent a power of two,
	in the manner of strconv.FormatFloat with the 'b' format,
	e.g. -123456p-78
%e	scientific notation, e.g. -1.234456e+78
%E	scientific notation, e.g. -1.234456E+78
%f	decimal point but no exponent, e.g. 123.456
%F	synonym for %f
%g	%e for large exponents, %f otherwise. Precision is discussed below.
%G	%E for large exponents, %F otherwise
%x	hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20
%X	upper-case hexadecimal notation, e.g. -0X1.23ABCP+20

*** 字符串和切片

%s	the uninterpreted bytes of the string or slice
%q	a double-quoted string safely escaped with Go syntax
%x	base 16, lower-case, two characters per byte
%X	base 16, upper-case, two characters per byte

*** 指针

%p	address of 0th element in base 16 notation, with leading 0x

3、系统保留关键字和预定义标识符

在这里插入图片描述

Golang中的运算符

1、运算符基本介绍

运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等

没有三元运算符

2、数值计算问题(插入)

在学习算术运算符之前,需要先了解一下数值之间的计算问题,上面也提到过,不同类型的数值不能计算,但是说的比较笼统,当时也没去深入了解。现在做以下总结。
主要分为三种情况:
1、返回值 = 常量 + 常量
2、返回值 = 常量 + 变量
3、返回值 = 变量 + 变量

*** 第一种情况

package main

import (
	"fmt"
)
	
func main() {

	/*
		1、返回值 = 常量 + 常量
			要求:常量显式的值必须是返回值能够接受的类型。
				但是也有例外,比如 var x int = 10.0 / 10	10.0显然不是int能够接受的,但是因为小数点后面是0所以也可以接受这种情况
				注意:整型本身就可以接受小数点后面全是0情况的数,正因为此,上面的情况才可以执行。
	*/
	var x int32 = 10 * 10
	fmt.Println(x)
	
	x = 10.0
	fmt.Printf("x type = %T, x = %d\n", x, x)
	
	x = 10.0 / 10
	fmt.Println(x)
	
	//x = 10.1 / 10	  // 10.1显然不可能能够赋值给int32类型,编译报错
	//fmt.Println(x)
	
}

在这里插入图片描述
*** 第二种情况

package main

import (
	"fmt"
)
	
func main() {

	/*
		2、返回值 = 常量 + 变量
			要求1:和常量 + 常量的情况一样
			要求2:变量的类型和返回值类型必须要一致
				
	*/
	var x float64 = 10.9
	var result float64 = x + 36	//可以通过,类型一致
	fmt.Println(result)
	
	var y float32 = 10.0
	result = y + 36		//编译出错,y和返回值类型不一致
	fmt.Println(result)
}

在这里插入图片描述
*** 第三种情况

package main

import (
	"fmt"
)
	
func main() {

	/*
		3、返回值 = 变量 + 变量
			要求:变量的类型和返回值类型必须要一致
	*/
	
	var x float32 = 10.2
	var y float64 = 10.3
	fmt.Println(x + y)
}

在这里插入图片描述

3、算术运算符

算术运算符一览表
详解
package main

import (
	"fmt"
)

func main() {
	/*
		除法运算特点
	*/
	//如果两个整数相除,那么会结果会去掉小数部分,只保留整数部分,无论返回值整型还是浮点型
	var x int = 10 / 4
	fmt.Printf("x = %d, x type = %T\n", x, x)

	var y float64 = 10 / 4
	fmt.Printf("y = %f, y type = %T\n", y, y)

	//如果要保留小数位,就要用浮点数参与运算
	var z float64 = 10.0 / 4
	fmt.Printf("z = %f, z type = %T\n", z, z)
}

在这里插入图片描述

package main

import (
	"fmt"
)

func main() {
	/*
		取余运算特点
			取余只对整数
	*/
	// 取余公式 a % b = a - a / b * b
	fmt.Println("10 % 3 =", 10 % 3) // =1
	fmt.Println("-10 % 3 =", -10 % 3) // = -10 - (-10) / 3 * 3 = -10 - (-9) = -1
	fmt.Println("10 % -3 =", 10 % -3) // =1
	fmt.Println("-10 % -3 =", -10 % -3) // =-1
}

2、++ –

package main

import (
	"fmt"
)

func main() {
	
	/*
		自增自减
			只能写在变量的后面
			只能单独写在一行,成一条语句,不能和其他语句混合使用
			这些强制性规定可以除去c等高级语言中容易出现的问题
	*/
	var x int = 9

	x--	//等价于 x = x - 1
	fmt.Printf("%d\n", x)	//8

	x++	//等价于 x = x + 1
	fmt.Printf("%d\n", x)	//9
}
注意事项

4、关系运算符(比较运算符)

基本介绍结果都是 bool 型
一览图
package main

import (
	"fmt"
)

func main() {
	
	var x int = 90
	var y int = 100

	fmt.Println("x == y ?", x == y)  	//false
	fmt.Println("x != y ?", x != y) 	//true
	fmt.Println("x <= y ?", x <= y) 	//true
	fmt.Println("x >= y ?", x >= y) 	//false
	fmt.Println("x < y ?", x < y)  		//true
	fmt.Println("x > y ?", x > y)  		//false

	/*
		比较运算符和算术计算时一样,如果是两个变量比较,他们的类型必须完全一致
		如果两个都是常量,那么他们没有强制要求
		如果一个是变量一个是常量,那么常量的显式数值必须是和变量一致(除了浮点型时,小数点后面全是0)
	*/
	// var z int8 = 0.0
	// fmt.Println("x > z ?", x > z) //invalid operation: x > z (mismatched types int and int8)

	fmt.Println("10 > 10.2 ? ", 10 > 10.9)		// false

	//fmt.Println("x > 10.9 ? ", x > 10.9)		// .\go1.go:26:33: 10.9 (untyped float constant) truncated to int
	fmt.Println("x > 10.0 ? ", x > 10.00000) 	// true
}

5、逻辑运算符

基本介绍注意事项和细节说明
  1. &&也叫短路与:如果第一个条件为 false,则第二个条件不会判断,最终结果为 false
  2. ||也叫短路或:如果第一个条件为 true,则第二个条件不会判断,最终结果为 true
    这种情况和其他语言是一样的。
package main

import (
	"fmt"
)

func test() bool {
	fmt.Println("Testing...")
	return true
}

func main() {
	
	var age int = 40

	if age < 30 && test() {
		fmt.Println("yes")
	}

	if age > 30 || test() {
		fmt.Println("no")
	}

}

在这里插入图片描述

6、赋值运算符

基本介绍
赋值运算符分类特点

7、位运算符

*** 说明
位运算符是基于二进制的计算
在这里插入图片描述

8、其他运算符

在这里插入图片描述
和c语言的使用方式一样。* 在声明变量的时候是指针变量,当用 和一个指针变量配合使用 *x的时候就是取x指针变量所指向的值。

9、运算符优先级和结合律

一览表

10、键盘输入

步骤
  1. 导入 fmt 包
  2. 调用 fmt 包的 fmt.Scanln() 或者 fmt.Scanf()
    在这里插入图片描述
    在这里插入图片描述
    1、Scanln
package main

import (
	"fmt"
)

func main() {
	
	//录入姓名、年龄、薪水、是否通过考试
	//1、使用fmt.Scanln
	var name string
	var age byte
	var sal float32
	var isPass bool

	fmt.Println("请输入姓名: ")
	fmt.Scanln(&name)
	fmt.Println("请输入年龄: ")
	fmt.Scanln(&age)
	fmt.Println("请输入薪水: ")
	fmt.Scanln(&sal)
	fmt.Println("请输入是否通过考试: ")
	fmt.Scanln(&isPass)

	fmt.Printf("姓名 %v\t, 年龄 %v\t, 薪水%v\t, 是否通过考试 %v\t\n", name, age, sal, isPass)
	
}

在这里插入图片描述
2、Scanf

package main

import (
	"fmt"
)

func main() {
	
	//录入姓名、年龄、薪水、是否通过考试
	//2、使用fmt.Scanf
	var name string
	var age byte
	var sal float32
	var isPass bool

	fmt.Println("请输入你的姓名,年龄,薪水,以及是否通过考试 , 空格隔开")

	fmt.Scanf("%s %d %f %t", &name, &age, &sal, &isPass)

	fmt.Printf("姓名 %v\t, 年龄 %v\t, 薪水%v\t, 是否通过考试 %v\t\n", name, age, sal, isPass)
	
}

在这里插入图片描述

11、进制

在这里插入图片描述
在这里插入图片描述

package main

import (
	"fmt"
)

func main() {

	/*
		右移运算符 >>:低位溢出,符号位不变,并用符号位补溢出的高位
		左移运算符 <<: 符号位不变,低位补 
	*/
	
	var x int = 4
	result := x >> 2	//相当于x / (2的2次方)
	result1 := 16 >> 3  //相当于 16 / (2的3次方)

	fmt.Println(result)
	fmt.Println(result1)

	fmt.Println(-1 << 2)	//相当于-1 * (2的2次方)
}

在这里插入图片描述

Golang中的程序流程控制

1、基本介绍

流程控制主要是顺序流程,分支流程和循环流程。

2、分支语句

1. 单分支if

基本语法
if 条件表达式 {
		执行代码
	}
//执行代码只有一行也要加上 {}
//可以在if中直接定义一个变量,但是不能使用var,所以只能用 := 的形式
//但是只能创建一个变量,多了会报错。
//if条件表达式不能是赋值语句
测试
package main

import (
	"fmt"
)

func main() {

	//if单分支
	var age int
	fmt.Scanf("%d", &age)

	if age > 18 {
		fmt.Printf("你是成年人\n")
	}

	//golang支持在if中直接定义一个变量,用分号隔开。只能用 := 形式定义变量
	if salary := 18888.8; salary > 10000 {
		fmt.Printf("你的薪资高于平均水平\n")
	}
}

2. 双分支 if else

基本语法
	/*
		1、必执行其中一条分支
		2、else { 不能另起一行,否则语法错误
	*/
	if 条件表达式 {
		执行代码
	} else {
		执行代码
	}
测试
package main

import (
	"fmt"
)

func main() {

	//if else双分支
	var age int
	fmt.Scanf("%d", &age)

	/*
		1、必执行其中一条分支
		2、else { 不能另起一行,否则语法错误
	*/
	if age > 18 {
		fmt.Printf("你是成年人\n")
	} else {
		fmt.Println("你是未成年人")
	}

}
package main

import (
	"fmt"
)

func main() {

	//判断是否是闰年
	if year := 2009; (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {
		fmt.Println("year is 闰年")
	} else {
		fmt.Println("year is 平年")
	}
}

3. 多分支 if else if…、switch

1、if else if … [else]
出现分支嵌套最多不要超过三层。

if 条件表达式1 {
		执行代码1
	} else if 条件表达式2{
		执行代码2
	}
	... else {
		执行代码
	}

	//只有一个执行入口
	//else 不是必须的
基本介绍不需要再加 break
基本语法
  1. switch 的执行的流程是,先执行表达式,得到值,然后和 case 的表达式进行比较,如果相等,就匹配到,然后执行对应的 case 的语句块,然后退出 switch 控制。
  2. 如果 switch 的表达式的值没有和任何的 case 的表达式匹配成功,则执行 default 的语句块。执行后退出switch的控制。
  3. golang 的 case 后的表达式可以有多个,使用 逗号 间隔.
  4. golang 中的 case 语句块不需要写 break , 因为默认会有,即在默认情况下,当程序执行完 case 语句块后,就直接退出该 switch 控制结构。
注意事项和细节
  1. case/switch 后是一个表达式( 即:常量值、变量、一个有返回值的函数等都可以)
    在这里插入图片描述
  2. case 后的各个表达式的值的数据类型,必须和 switch 的表达式数据类型一致。
package main

import (
	"fmt"
)

func main() {

	var x int8 = 10
	var y int32 = 10

	switch x {
	case y:  // invalid case y in switch on x (mismatched types int32 and int8)
		fmt.Println("yes")
	default:
		fmt.Println("no")
	}
	
}
不推荐使用fallthrough继续执行下一个 case

4. if和switch比较

总结了什么情况下使用 switch ,什么情况下使用 if

  1. 如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用 swtich语句,简洁高效。
  2. 其他情况:对区间判断和结果为 bool 类型的判断,使用 if,if 的使用范围更广。

3、 循环语句

没有c中的while和do...while循环

for循环

基本语法
package main

import (
	"fmt"
)

func main() {

	for i := 1; i < 10; i++ {
		fmt.Println(i) // 输出1 - 9
	}
	
}
使用细节和注意事项
布尔值的表达式
package main

import (
	"fmt"
)

func main() {

	var i int = 1
	for i < 10 {
		fmt.Println(i)
		i++
	}
	
}
  1. for 循环的第三种使用方式
    在这里插入图片描述
package main

import (
	"fmt"
)

func main() {

	var i = 1
	for {
		if(i < 10){
			fmt.Println(i)  // 输出1 - 9
		} else {
			break
		}
		i++
	}
}
传统遍历字符串
package main

import (
	"fmt"
)

func main() {

	var str = "HELLO WORLD!!"
	//len是10几个内置函数之一
	for i := 0; i < len(str); i++ {
		fmt.Printf("%c", str[i])
	}

	fmt.Println()
}

在这里插入图片描述

for-range方式
package main

import (
	"fmt"
)

func main() {

	var str = "HELLO WORLD!!你好"

	for index, val := range str {	//index和val不需要是已定义好的变量
		fmt.Printf("index = %d, val = %c \n", index, val)
	}

}

在这里插入图片描述

细节讨论按照字节来遍历for-range遍历方式是按照字符方式遍历。因此如果有字符串有中文,也是 ok的
将 str 转成 [ ]rune 切片

4、跳转语句

1. break语句

基本介绍
注意事项和使用细节默认跳出最近的循环指定标签来跳出指定的循环

2. continue语句

*** 基本介绍
continue语句默认用于结束本次循环,继续执行下一次循环。
continue语句出现在多层嵌套的循环语句中时,可以通过标签指明要跳过的哪一层循环,这个和前面的break使用规则一样。
在这里插入图片描述

4. 跳转控制语句goto

无条件地转移到程序中指定的行通常与条件语句配合使用一般不主张使用goto语句

5. 跳转控制语句return

基本介绍
  1. 如果return是在普通的函数,则表示跳出该函数,即不再执行函数中 return后面代码,也可以理解成终止函数。
  2. 如果return是在main函数,表示终止main函数,也就是说终止程序。

6. 总结

上面几种跳转语句和c语言基本都是一致的,也就是break和continue添加了标签的功能。