Go基础之流程[if, for,switch]和函数[func]

流程控制
  流程控制有三大类:条件判断, 循环控制, 无条件跳转

  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 [小路写·过去篇]

posted @ 2017-12-23 13:50  漫步小路  阅读(330)  评论(0编辑  收藏  举报