Golang-Study
Golang-Study-Note
参考教程视频:狂神说
https://www.bilibili.com/video/BV1ae41157o9?p=1&vd_source=7936683721e7dee1c207a6374e8dfb72
一、Golang语言发展史
1.Golang语言的诞生
2.版本发布
3.Go语言使用场景
二、Go语言开发环境搭建
1.下载和安装GO-SDK
Go语言官网:https://golang.org/
Go语言中文网:https://studygolang.com/
安装GO-SDK(SDK即:Software Development Kit 软件开发工具包),Windows系统下可以选择msi(图形界面安装包,根据图形界面提示进行选择和安装),或者zip(编译后的压缩包,解压缩即可使用,需要手动配置环境变量)
2.环境配置
(1)GOROOT
创建GOROOT环境变量存放GO-SDK的安装目录地址
(2)GOPATH
GOPATH存放Go语言项目代码,需要在GOPATH目录下创建src、pkg、bin三个目录
(3)path
在环境变量path中添加%GOROOT%\bin,即GO语言的开发工具(GO-SDK)安装目录下的bin目录,bin目录存放了Go语言的编译工具等。
(4)检查配置是否生效
打开cmd(Win+R),在任意目录下使用go version命令查看GO-SDK的版本,正确输出安装版本即表示环境配置成功。
go version
查看GO-SDK配置的环境
go env
3.下载和安装GoLand
GoLand官网:https://www.jetbrains.com/go/
安装
三、第一个Go语言程序
1.记事本编写GO语言程序并运行
(1)创建一个hello.go文件,使用记事本打开,编写第一个GO语言程序
package main
import "fmt" //导入系统资源包
func main() {
fmt.Printf("Hello World!") //输出指定字符串
}
(2)运行hello.go
在hello.go文件所在目录下打开cmd(在目录地址栏直接输入cmd并enter),使用go run 命令运行GO程序
go run hello.go
(3)运行结果
2.GoLand编写hello.go程序并运行
(1)新建一个GO语言程序
(2)编写hello.go程序
// package Hello_Golang
package main
import "fmt" //导入系统资源包
func main() {
fmt.Printf("Hello World! Hello Golang!") //输出指定字符串
}
运行结果
四、Golang基本语法
1.注释
(1)单行注释
//注释内容
(2)多行注释
/*
注释内容
*/
2.变量
(1)变量的定义
1)标准变量定义
//1.定义变量使用var关键字,注意GO语言的语句不需要分号结尾(这与java和c语言不同)
//2.定义变量的基本格式:var 变量名 变量类型
var name String
2)批量定义多个变量
//批量定义多个变量使用var关键字和大括号
var(
name String
age int
)
3)简短变量的定义
/*
格式化输出使用fmt.Printf()
格式化输出符号:%T数据类型、%t数据值、%s字符串类型、%d数值型
*/
(2)变量交换
GO语言可以直接进行变量值的交换,不需要定义中间变量来暂存变量值。
(3)匿名变量
(4)变量的作用域
(5)常量
常量的定义使用关键字const,GO语言程序中有两种常量定义方式显式定义和隐式定义,隐式定义常量不需要给出常量的数据类型,编译器会自动推到其数据类型。
特殊常量iota
3.数据类型
基本数据类型:
(1)布尔型:bool
其值只能是true或者false
(2)整型:byte、int、int8、int16、int32、int64、uint、uintptr、uint8、uint16、uint32、uint64
int表示有符号,uint表示无符号
int8取值范围:-(27)~(27-1),即 -128 ~ 127
uint8取值范围:0 ~ (2^8-1),即 0 ~ 255
int16、int32、int64、uint16、uint32、uint64...依此类推
(3)浮点型:float32、float64、complex64、complex128
(4)字符串类型:string(注意string的首字母是小写的)
字符使用单引号括起来,字符的类型是int32
字符串使用双引号括起来,字符串类型是string
数据类型转换
GO语言中的数据类型转换必须是显示定义的
派生数据类型:
(1)指针(pointer)
(2)数组(array)
(3)结构体(struct)
(4)通道(channel)
(5)切片(slice)
(6)函数(function func)
(7)接口(interface)
(8)Map
4.运算符
(1)算数运算符
(2)关系运算符
(3)逻辑运算符
(4)位运算符
位运算符是操作二进制数的,与逻辑运算符容易混淆,需要注意
查看二进制数值,控制输出使用符号 %b
(5)赋值运算符
(6)其他运算符
5.获取键盘输入
6.命名规范
7.流程控制语句(程序结构)
(1)顺序结构
(2)分支结构
1)if语句
package main
import "fmt"
// 使用if语句实现学生分数评级
func main() {
fmt.Println("请输入分数:")
var score float32
fmt.Scan(&score)
if score <= 100 && score > 90 {
fmt.Println("A")
} else if score <= 90 && score > 80 {
fmt.Println("B")
} else if score <= 80 && score > 70 {
fmt.Println("C")
} else if score <= 70 && score > 60 {
fmt.Println("D")
} else if score <= 60 && score > 0 {
fmt.Println("不及格")
} else {
fmt.Println("输入的格式不正确!")
}
}
if语句的嵌套
2)switch语句
package main
import (
"fmt"
)
// switch语句,匹配的条件是基本数据类型(整型、浮点型、字符串类型和布尔类型)
func main() {
//调用自定义函数
//switch1()
switch2()
}
// 1.switch语句
func switch1() {
fmt.Println("请输入姓名:")
var name string
fmt.Scan(&name)
switch name {
case "John":
fmt.Printf("I am %s\n", "John")
case "Lucy":
fmt.Printf("I am %s\n", "Lucy")
case "Lily":
fmt.Printf("I am %s\n", "Lily")
default:
fmt.Println("不在学生名单中!")
}
}
// 2.fallthrough实现case穿透
func switch2() {
flag := false
switch flag {
case false:
fmt.Println("条件为false")
fallthrough //fallthrough实现case穿透
case true:
//break阻止case穿透
if flag == false {
break
}
fmt.Println("条件为true")
default:
fmt.Println("均不满足条件!")
}
}
(3)循环结构
break和continue
循环结构demo
package main
import "fmt"
/*
GO语言流程控制
1.顺序结构:存续执行代码
2.分支结构(选择结构):if语句、switch语句
3.循环结构:for语句
*/
// for语句
func main() {
//调用自定义函数
//for1() //累计求和
//for2() //打印方阵
//for3() //打印九九乘法表
for4() //break和continue
}
func for1() {
/*
累计求和
*/
var sum int
for i := 1; i <= 10; i++ {
sum += i //即sum = sum + i
fmt.Println(sum)
}
fmt.Printf("sum=%d\n", sum)
}
func for2() {
/*
打印一个5*8的方阵
*/
for i := 1; i <= 5; i++ {
for j := 1; j <= 8; j++ {
fmt.Printf(" * ") //打印输出*
}
fmt.Println() //换行
}
}
func for3() {
/*
打印九九乘法表
*/
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d*%d=%d ", j, i, i*j)
}
fmt.Println() //换行
}
}
func for4() {
/*break和continue
1.break:跳出循环
2.continue:结束本次循环,继续执行下一次循环
*/
for i := 0; i <= 5; i++ {
if i == 3 {
break //跳出循环
}
fmt.Println(i)
}
fmt.Println("================ 分隔线 ================")
for i := 0; i <= 5; i++ {
if i == 3 {
continue //跳出本次循环,继续执行下一次循环
}
fmt.Println(i)
}
}
(4)string
字符串相关操作demo
package main
import "fmt"
//字符串相关操作
func main() {
//定义一个字符串str
str := "Hello,World!"
//1.获取字符串长度:使用len函数
fmt.Println(len(str))
fmt.Println("====================================")
//2.获取字符串中的单个字符,下标从0开始计算
fmt.Println(str[6]) //单个字符会打印其在ASCII编码表对应的值
fmt.Printf("%c\n", str[6]) //格式化输出,单个字符使用符号%c
fmt.Println("====================================")
//3.for语句遍历输出字符串的每个字符
for i, v := range str {
fmt.Printf("%d %c\n", i, v) //格式化输出,打印下标和下标对应的字符
}
fmt.Println("====================================")
for i := range str {
fmt.Printf("%c ", str[i])
}
}
8.函数
(1)函数的定义和使用
(2)可变参数 ...
1.函数的参数类型确定,但是参数个数不确定的情况下可以使用可变参数。
2.可变参数一般放在参数列表的最后,一个函数最多只能有一个可变参数。
(3)参数的传递
1.数值型的参数:值传递,即操作数据本身,值传递的是参数值的副本,对原有数据不产生影响。
2.引用型的参数:内存地址的传递,即直接操作在内存地址上,会对该地址的值产生影响。
数组的定义
数组,即
/*
数组的定义格式:
数组名 := [数组长度] 数组类型 {value1,value2...value}
*/
切片的定义
切片(slice)是可扩容的数组
/*
切片的定义格式:切片的长度可变,所以不用设置切片的长度
切片名 := [] 切片类型 {value1,value2...value}
*/
(4)变量的作用域
(5)递归函数
1.函数调用本身即为递归,递归函数需要一个出口,避免死循环。
2.一般情况下建议尽可能减少使用递归函数,因为递归会占用较多的内存空间,会降低性能。
(6)defer关键字:延迟执行
多个defer关键字,采用先进后出(栈)的模式
9.函数的高级应用
(1)函数的数据类型
1.函数本身就是一种数据类型,使用格式化输出符号%T可以查看数据类型。
注意:不能带上括号,带上括号时就会调用函数,直接使用函数名即可
2.不带上括号,单个函数名可以看作变量,即可以定义一个函数类型的变量并进行赋值
(2)匿名函数
匿名函数,即没有函数名的函数,一般匿名函数只会执行一次
(3)回调函数和函数的闭包
1.回调函数:将函数作为其他函数的参数,做参乎上的函数称为回调函数
2.函数的闭包:将函数作为其他函数的返回值,形成函数的闭包
高阶函数和回调函数
1.高阶函数:接收其他函数作为参数的函数称为高阶函数
2.回调函数:把自身作为参数的函数称为回调函数
package main
import "fmt"
/*
函数的高级应用:
4.回调函数,即将匿名函数作为函数的参数
*/
func main() {
//3.调用高阶函数,将自定义的函数作为参数传递
oper(20, 30, addNum)
oper(200, 130, subNum)
//4.也可以将匿名函数直接作为参数
oper(99, 0, func(a, b int) int {
if b == 0 {
fmt.Println("除数不能为0!")
return 0
}
return a / b
})
}
// 1.定义一个高阶函数:接收其他函数作为参数的函数
func oper(a, b int, fun func(int, int) int) {
res := fun(a, b) //调用传递进来的函数,并将返回值赋值给变量res
fmt.Println("res=", res) //输出res的变量值
}
// 2.自定义函数
func addNum(i, j int) int {
return i + j
}
func subNum(i, j int) int {
return i - j
}
函数的闭包
将函数作为其他函数的返回值,形成函数的闭包
package main
/*
函数的高级应用:
5.函数的闭包,即将匿名函数作为函数的返回值,形成函数的闭包结构
实际开发中尽量减少使用闭包结构,因为闭包结构容易造成代码阅读上的混淆,会增加代码维护的成本
*/
import "fmt"
func main() {
//调用闭包结构的函数
i := increment()
fmt.Println(i) //2
}
// 定义一个闭包结构的函数
func increment() int {
//1.定义局部变量i
count := 1
//2.定义一个匿名函数,实现自增,使用外层函数的局部变量作为参数并执行
val := func(i int) int {
return count + 1
}(count) //3.内层匿名函数调用了外层函数的局部变量count
//4.将内层函数的返回值返回给外层函数
return val
}