流程控制
流程控制有三大类:条件判断, 循环控制, 无条件跳转
if:所有语言 都有的一种判断:如果满足就做 不满足就做另一件
if x > 5 {
fmt.println("比5大")
} else {
fmt.println("比5小")
}
不同点:GO在条件判断语句里允许声明一个变量,作用范围在该条件逻辑块内
if a := computedValue(); a>5 {
fmt.println("比5大")
} else {
fmt.println("比5小")
}
a出了if语句块那么也就超范围 失效了
fmt.println(a)
多条件: if xxx{} else if xxx{} else{}
goto goto跳转必须在当前函数内定义好的标签。(标签大小写敏感)
func myFunc() {
i := 0
Here:
println(i)
i++
goto Here
}
for:
Go里控制逻辑,它可以用来循环读取数据 又能控制逻辑 还能迭代操作
for xx1, xx2, xx3 { xxx } 其中xx1,xx2, xx3都是表达式
//例子
package main
import "fmt"
func main(){
sum :=0;
for index :=0; index < 10; index ++ {
sum += index
}
fmt.Println("sum is" , sum)
}
有时候需要进行多个赋值操作,go没有 所以使用平行赋值i, j= i + 1 ,j-1
有时候可以忽略条件1和条件3
sum := 1
for ; sum <1000; {
sum += sum
}
; 也可以省略
在循环体中有两个关键操作 break和continue。break跳出循环 continue 跳出本次循环
break 和 continue 可以跟着标号 用来调到多重循环中的外层循环
for配合 range 可以用于读取slice和maip的数据
for k, v:=range map {
fmt.println("map",k)
fmt.println("map",v)
}
!!!由于GO支持"多值返回",并且对"多声明变量不用会报错"在这种情况下 可以使用_来丢弃不需要使用的返回值
for _, v := range map{
fmt.Println("maps val:",v)
}
switch
有时候你需要写很多的if-else来实现逻辑处理那么可以用switch来代替
switch sexpr {
case expr1:
some instructions
case expr2:
some instructions
case expr3:
some instructions
default:
other code
}
其中 sexpr 和exprx 的类型要保持一致。Go的switch非常灵活,表达式不必是常量或证书,执行过程从上到下,直到找到匹配项:
如果switch没有表达式,它会匹配true
go里面switch中 默认每个case后面带有break,配对成功后不会向下执行而是跳出switch 但是可以用fallthrough 强制执行后面的case代码
函数:
函数是Go里面的核心设计,通过关键字func来声明
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
//这里处理逻辑代码
//返回多个值
return value1, value2
}
func 是声明一个函数 funcName
函数可以有一个或者多个参数,每个参数后面带有类型,通过,分割
函数可以返回多个值
//例子
func max(a,b int) int {//a,b int 都是int 缩略一个int
if a > b {
return a
}
return b
}
func main() {
x := 3
y := 4
z := 5
max_xy := max(x, y) //调用函数max
max_xz := max(x, z)
fmt.Printf("max(%d,%d)=%d\n", x, y, max_xy)
}
多返回值
Go函数支持变参,接受变参的函数是有着不定数量的参数的 但是类型保持一致
func myfunc(arg ...int) {}
arg ... int 告诉GO这个函数接受不定数量的参数 在函数体中arg是个slice
for _, n := range arg {
fmt.Pringtf("and the number is : %d\n", n)
}
传值和传指针
当我们传一个参数值到被调用函数里面时,世纪穿了这个值得一份copy 当在被调用函数中修改参数值的时候,
调用函数中相应实参不会发生任何变化,因为数值变化只作用在copy上。
例子:
package main
import "fmt"
// 函数实现+1操作
func add1(a int) int {
a = a + 1
retrun a //返回一个新值
}
func main() {
x := 3
fmt.Println("x =", x) //应该输出 "x = 3"
x1 := add1(x) //调用add1()
fmt.Println("x + 1 =", x1) //应该输出"x+1 =4"
fmt.Println("x = ", x) //应该输出 "x = 3"
}
!!!上面x 调用了 add1(x) 并且在add1中执行 a = a + 1 操作,但是x变量的值没有发生变化
解析原因: 当我们调用add1的时候 add1接收的参数其实是x的copy 而不是x本身
如果传本身呢? 那就是要传指针了啊
package main
import "fmt"
//简单的一个函数,实现了参数+1的操作
func add1(a *int) int {
*a = *a + 1 //修改了a的值
retrun *a //返回新值
}
func main() {
x := 3
fmt.Println("x=", x) //应该输出"x=3"
x1 := addr1(x)
fmt.Println("x+1", x) //应该输出 4
fmt.Println("x", x) //应该输出4
}
// 传指针的好处
1.传指针使得多个函数能操作同一个对象
2.传指针比较轻量级(8bytes),只是传内存地址,我们尅用指针传递体积大的结构体。
如果用参数值传需要copy会花额外多的系统开销。所以传递大的结构体的时候,用指
针是一个明确的选择
3.Go语言中string, slice, map这三种类型的实现机制类似于指针 可以直接传递 不用取地址后传递指针
defer:
GO语言中有种不错的设计 延迟语句 defer。可以在函数中添加多个defer.并且defer按照逆序进行执行
func ReadWrite() bool{
file.Open("file")
//做一些工作
if filurex {
file.Close()
retrun false
}
if filurey {
file.Close()
retrun false
}
file.Close()
retrun false
}
上面代码太重复 defer解决了这个问题
func ReadWriter() bool{
file.Open("file")
defer file.Close()
if failurex {
return false
}
if failureY {
renturn false
}
return ture
}
!!!如果很多defer引用,那么defer是采用后进先出的模式
函数作为值,类型
在Go中函数也是变量之一 可以用type来定义。它的类型就是所拥有相同的参数,相同的返回值的一种类型
type typeName func() type
package main
import "fmt"
type testInt func(int) bool //声明了一个函数类型
func isOdd(integer int) bool {
if integer % 2 == 0 {
return false
}
retrun true
}
func isEven(integer int) bool {
if integer % 2 == 0 {
return true
}
retrun false
}
// 声明的函数类型在这个地方做了一个参数
func filter(slice []int, f testInt) []int {
var result [] int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
func main() {
slice := [] int {1, 2, 3, 4, 5, 7}
fmt.Println("slice = ", slice)
odd := filter(slice, isOdd) // isOdd这个函数当做值 传递到了 filter这个函数里边
fmt.Println("Odd elements of slice are: ", odd)
even := filter(slice, isEven)
fmt.Println("Even elements of slice are: ", even)
}
用途: 函数当做值 和类型在我们写一些通用接口时候非常有用 上面例子中testInt类型是个函数类型。 我们可以实现很多种逻辑使得我们程序变得非常灵活
panic和Recover
main 函数 和Init 函数
GO里面有两个保留函数: init函数 (应用于所有package) 和main函数 (只能应用于package main)
这2个函数定义时候不能有任何参数和返回值
两个函数一个包只限制有一个
GO会自动调用init() 和main() 不需要任何地方调用
init() 是可选的 但是main 是必须的
先执行main包 --- 然后导入其他包 重复只导入一次 ----init包
import 包
GO代码经常用到import这个命令来导入包文件
import( "fmt")
fmt是Go语言的标准库 , 去goroot 下加载该模块,
go也支持其他2种方式来加载自己模块
1.相对路径 :import "./model" //当前文件同一目录的model目录,不推荐这种方式导入
2.绝对路径 : import "shorturl/model" //架子啊gopath/src/shorturl/model模块
特殊导入import
1.点操作:
import(
. "fmt"
)
这个.的意思是 这个包导入 有点 后在引用这个包的函数时候不需要前缀 ---> print()
2.别名操作
import(
f "fmt"
)
别名操作调用包函数时候 前缀变成我们的前缀 ---> f.print()
3._操作
import (
"database/sql"
_"github.com...."
)
_操作就是引入该包,不引入包里面函数,而是调用该包里面的init函数
2017年12月23日13:49:48 [小路写·过去篇]