Go基础语法

流程控制

一共有三种:顺序结构,选择结构,循环结构

if语句

/*
if与else if的区别:
1:if无论是否满足条件都会向下执行,直到程序结束,else if 满足一个条件就会停止执行。
2:由于if都会执行一遍,则可能会同一个需要判断的事件,会进入2个if语句中,出现错误,而else if就不会发生这样的事情。
*/
func main() {
var a int = 15
var score int = 80
if a > 20 {
fmt.Println("a大于20")
}
if a > 10 {
fmt.Println("a大于10")
} if score >= 90 && score <= 100 {
fmt.Println("A")
} else if score >= 80 && score < 90 {
fmt.Println("B")
} else if score >= 70 && score < 80 {
fmt.Println("C")
} else if score >= 60 && score < 70 {
fmt.Println("D")
} else {
fmt.Println("F")
}
}

if嵌套

// 通过if嵌套实现二次验证密码
func main() {
var a, b int
var pwd int = 20221108 fmt.Print("请输入密码:")
fmt.Scan(&a)
if a == pwd {
fmt.Print("请再次输入密码:")
fmt.Scan(&b)
if b == pwd {
fmt.Println("登录成功")
} else {
fmt.Println("登录失败,密码输入不一致")
}
} else {
fmt.Println("密码错误")
}
}

switch语句

// switch语句
func main() {
var score int = 90 //case来匹配 switch后的结果
switch score {
case 90:
fmt.Print("A")
fallthrough //通过此关键字实现穿透
case 80:
fmt.Print("B")
//由于每一个case自带break效果 只能穿透到这里 如果继续穿透 需要再添加fallthrough
fallthrough
case 70, 60, 50:
//如果想过提前结束可以添加break
if score == 80 {
break
}
fmt.Print("C")
default:
fmt.Print("D")
} //switch的默认条件是 bool=ture
switch {
case false:
fmt.Print("false")
case true:
fmt.Print("true")
default:
fmt.Println("其他")
}
}

与java不同case后默认自带break效果 所以一般不存在穿透效果

所以需要使用fallthrough关键字来实现穿透效果

单独使用fallthrough会强制穿透,不管下一个case中的条件是否满足所以可以搭配break使用

for循环

func main() {
//循环10次
for i := 0; i < 10; i++ { //i的作用域只在for循环中哦
fmt.Println(i)
} //计算从1到10的和
sum := 0
for i := 1; i <= 10; i++ {
sum += i
}
fmt.Println(sum) j := 0
for j < 110 {
fmt.Println(j)
j++
} }

for循环中的所有参数都可以省略有这么几种情况:

1、for :循环条件: 这样需要声明变量起始值 并在循环体中控制 变量的增减

2、for {} 这就是无限循环

练习

func main() {
//打印一个 5*5的星号方阵
fmt.Println("5*5的星号方阵哦")
for i := 1; i <= 5; i++ {
for i := 1; i <= 5; i++ {
fmt.Print(" *")
}
fmt.Println()
} //打印九九乘法表
fmt.Println("九九乘法表")
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d*%d=%d/t", j, i, i*j)
}
fmt.Println()
}
//这样也是可行的 不过效率就降低了
for i := 1; i <= 9; i++ {
for j := 1; j <= 9; j++ {
if j > i {
break
}
fmt.Printf("%d*%d=%d/t", j, i, i*j)
}
fmt.Println()
} }

break 与 continue

func main() {

   //break是直接结束本循环程序
for i := 0; i < 10; i++ {
if i == 5 {
break
}
fmt.Println(i)
} //continue跳过本次循环
for i := 0; i < 10; i++ {
if i == 5 {
continue
}
fmt.Println(i)
}
}

string

func main() {
str := "hello,my country"
fmt.Println(str) //获取字符串的长度
fmt.Println("字符串的长度为:", len(str)) //获取字符串指定的字节
fmt.Println("字节打印:", str[2]) //acsii编码值108
fmt.Printf("%c\n", str[2]) //for循环遍历字符串
for i := 0; i < len(str); i++ {
fmt.Printf("%c", str[i])
} for i, j := range str {//i 是字符串下标 j是字节
fmt.Print(i)
fmt.Printf("%c", j)
}
}

string中的字节不能被单独改变

函数

函数是基本的代码块 用于执行一个任务

func 函数名 (参数1,参数2,...)返回值类型 int,int,...{
函数体
return 返回结果
}
  • 无参无返回值、几个或没有参及返回值
func main() {

   fmt.Println(add(2, 3))
printinfo()
printinfo2("你好")
a, b := printinfo3("世界", "你好")
fmt.Println(a, b) } func printinfo() {
fmt.Println("我是无参无返回值")
} func printinfo2(str string) {
fmt.Println("我是有参无返回值", str)
} func printinfo3(str, st2 string) (string, string) {
return st2, str
} func add(a, b int) int {
c := a + b
return c
}

可变参数

func main() {
getSum(2, 56, 23, 12, 4, 2) } // 可变参数
func getSum(nums ...int) { //意为可变参数其实是一个数组?
sum := 0
for i := 0; i < len(nums); i++ {
sum += nums[i] }
fmt.Println(sum)
}
  • 这里可以看到 可变参数是如何定义的 变量名...数据类型
  • 其次通过调用函数,发现可变参数可以一直输入变量,所以可变参数要定义再最后
  • 而且同java 可变参数有且只有一个

值传递、引用传递

值传递 对象有基本类型 int string bool float array

/*
值传递 将arr中的值复制一份到arr2上 即开辟了两个空间
所以修改arr2中的元素并不会影响arr
使用值传递的数据有 基础类型,array,struct
*/
func main() {
//值传递
arr := [4]int{1, 2, 3, 4}
update(arr)
fmt.Println(arr)
fmt.Println("========================") str := "世界"
updateString(str)
fmt.Println(str) //引用地址传递
} func update(arr2 [4]int) {
fmt.Println(arr2)
arr2[0] = 100
fmt.Println(arr2)
} func updateString(str string) {
fmt.Println(str)
str = "你好"
fmt.Println(str)
}

引用类型 对象有 slice map chan...

/*
s1 与s2指向的空间是同一个 s2修改了一个值
s1也会随之变化
*/ func main() {
//切片 其实就是可以扩容的数组
s1 := []int{1, 2, 3, 4}
update2(s1)
fmt.Println(s1) } func update2(s2 []int) {
fmt.Println("传递的数据:", s2)
s2[0] = 100
fmt.Println("更新后:", s2)
}

变量作用域

  • 在函数中定义的变量叫做局部变量
  • 在函数外定义的变量叫做全局变量
// 定义全局变量
var num int = 100 func main() {
temp := 199 if b := 1; b < 10 {
temp := 99
num := 00
fmt.Println(temp) //遵循就近原则 99
fmt.Println(b)
fmt.Println(num) //0
}
fmt.Println(temp) // 199
//fmt.Println(b) b只能在if中使用 fmt.Println(num)
} func f1() {
num := 11
a := 1
fmt.Println(a)
fmt.Println(num) //11
} func f2() {
//fmt.Println(a) 不能使用其他函数中定义的变量
fmt.Println(num) //100
}
  • 一定要注意变量的作用域

defer 延迟执行

  • defer的作用同队列一样 先入后出
  • 当然并不意味着defer标识的函数会最后传入参数执行,程序还是顺序传入参数 然后最后执行
func main() {
a := 10
fmt.Println(a) //10
//参数 10传递进去了,不过被延迟到最后执行
defer f(a) // 10
a++
fmt.Println("我在defer后", a) // 11
} func f(s int) {
fmt.Println(s)
}

函数的理解

函数本身也是数据类型,所以函数也是变量,可以复制

func main() {
fmt.Println(f1) //f1在不加()下使用就是一个变量
fmt.Printf("%T\n", f1) //类型是func(int, int) 定义的函数是什么样的 类型就是什么样的
//定义一个函数类型变量
var f2 func(int, int) = f1
f2(2, 3) //输出 为 2 3 证明 f1 的值赋予了f2
fmt.Printf("%T\n", f2) //func(int, int)
fmt.Println(f2) //地址与f1一致 指向同一个空间 0x69fe60 } func f1(a, b int) {
fmt.Println(a, b)
}

匿名函数 go是可以函数式编程的

func main() {
ff1() //调用f1函数
ff2 := ff1 //将f1变量的值赋予f2
ff2() //匿名函数
func() {
fmt.Println("我是匿名函数")
}() //匿名函数自己调用自动 //匿名函数同普通函数一样可以添加参数、返回值
x := func(a, b int) int {
fmt.Println("我是匿名函数", a, b)
return a + b
}(1, 2) fmt.Println(x) } func ff1() {
fmt.Println("f1")
}

回调函数

  • 高阶函数 接受一个函数作为参数的函数
  • 回调函数 作为一个参数的函数
func main() {
//r := sum(1, 2)
//fmt.Println(r)
r1 := opear(1, 2, sum)
fmt.Println(r1) r2 := opear(3, 6, mul)
fmt.Println(r2) r3 := opear(4, 7, func(a int, b int) int {
return a * b
})
fmt.Println(r3) r4 := opear(8, 4, func(a int, b int) int {
if b == 0 {
return 0
}
return a / b })
fmt.Println(r4) } func sum(a, b int) int {
return a + b
} func mul(a int, b int) int {
return a - b
} func opear(a, b int, fun func(int, int) int) int {
r := fun(a, b)
return r
}

闭包

函数调用函数就会生成一个结构:闭包

一个外层函数,内有一个内层函数,内层函数会操作外层函数的局部变量

并且这个外层函数的返回值就是这个内存函数 这就是闭包结构

*一般来说当函数调用完毕 函数中的变量等应该会被销毁,但是闭包结构中的外层函数的局部变量不会随着外层函数的结束而销毁,因为内层函数还在继续使用

func main() {
r1 := inc()
fmt.Println(r1) v1 := r1() //1
fmt.Println(v1) //1
v2 := r1() //2
fmt.Println(v2) //2
fmt.Println(r1()) //3
fmt.Println(r1()) //4
fmt.Println(r1()) //5 //i重新计数
r2 := inc()
fmt.Println(r2)
v3 := r2() //1
fmt.Println(v3) //1
fmt.Println(r1()) //6
fmt.Println(r2()) //2 } func inc() func() int { //外层函数
//局部变量
i := 0
//定义一个匿名函数,给变量自增并返回
fun := func() int { //内层函数
i++ //操作外层函数局部变量
return i
}
return fun
}

Go_day02的更多相关文章

随机推荐

  1. P1062 [NOIP2006 普及组] 数列 题解

    目录 题目 思路 code 题目 P1062 [NOIP2006 普及组] 数列https://www.luogu.com.cn/problem/P1062 思路 先把 N 转换成 2 进制,再把这个 ...

  2. Hook新特性(一)

    基础Hook 1.useState const [state, setState] = useState(initialState); //返回一个state变量,指为initialState,set ...

  3. Java方法之什么是方法?

    方法详解 何谓方法? System.out.println(),那么它是什么呢? 1.System:类 2.out:对象 3.println():方法 Java方法是语句的集合,它们在一起执行一个功能 ...

  4. window server 2012R2部署asp.net core项目应用程序池自动停止

    当在windows  server 2012R2上部署asp.net core项目时,需要安装the Hosting Bundle,但当我们安装完dotnet-hosting后,浏览站点应用程序池会自 ...

  5. Access-Control-Allow-Origin php跨域报错

    Access-Control-Allow-Origin php跨域 解决办法: 1.PHP中echo:header(""Access-Control-Allow-Origin: * ...

  6. javaScript面向对象(继承篇)

    一.构造函数继承   function Parent() { this.money = '2亿' this.eat = function () { console.log('吃饭') } } func ...

  7. Angular+FileSaver实现导出(xlsx或ExcelJS)

    1.安装相关插件 npm install file-saver --savenpm install @types/file-saver --save-dev 一.xlsx(虽然强大,但是默认不支持改变 ...

  8. DNS服务器(简)

    服务端:192.168.182.187 客户端:192.168.182.16 windows客户端:192.168.182.17 1.安装相关服务 yum -y install bind bind-c ...

  9. Python使用requests和requests_toolbelt上传文件

    1.requests-toolbelt官方文档:https://pypi.org/project/requests-toolbelt/ 2.环境安装 pip install requests-tool ...

  10. JDK的安装及卸载

    JDK安装及卸载 卸载JDK 删除JAVA安装目录 删除java_home 删除path下关于Java的目录 java-version 查看是否仍能查看 安装JDK 百度搜索JDK8(性能稳定)找到下 ...