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 [小路写·过去篇]
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号