常量

118 阅读12分钟

定义: const

iota 在const 出现时将会垂直为0,

package main​import (    "fmt")//常量定义// 在程序运行期间不能修改,const (    code=200)// 批量声明常量,如果某一行没有赋值, 默认和上面一行一致const(    m1=100    m2=200    m3)// iota  类似于枚举const(    n1=iota   //0    n2     _    n3)​const(    d1,d2=iota+1, iota+2    d3,d4=iota+3,iota+4)​// 定义数据量级const(   _=iota   KB = 1 << (10 * iota)   MB = 1 << (10 * iota)   GB = 1 << (10 * iota)   TB = 1 << (10 * iota)   PB = 1 << (10 * iota))​func main() {    fmt.Println("KB",KB)    fmt.Println("MB",MB)    fmt.Println("GB",GB)    fmt.Println("TB",TB)    fmt.Println("PB",PB)}​

分支控制

package main​import (    "fmt")func main() {    //流程控制    var n int =80    if n>100 {        fmt.Printf("大家好%#v\n",n)    }else if n==100 {        fmt.Println("小盆友好。。。。。",n)    }else if n==90{        fmt.Println("========正常人")    }else {        fmt.Println("=============")    }   }

特殊写法

package main​import (    "fmt")func main() {    //流程控制    // n的作用域在  ifif n:=80; n>100 {        fmt.Printf("大家好%#v\n",n)    }else if n==100 {        fmt.Println("小盆友好。。。。。",n)    }else {        fmt.Println("=============")    }    fmt.Println("n",n)​}

for 循环

for 初始化语句;条件表达式;累加语句

package main​import (    "fmt")func main() {    //for 循环    for i:=0; i<10 ; i++{        fmt.Println("i",i)    }    //    var i int=5   for ; i<10;i++{     fmt.Println("i",i)   }   // 结束语句可以   for ; i<10 ;{​    fmt.Println("i",i)    i++   }   //死循环//    for {//     fmt.Println("=====",i)//    }​   //for range (键值循环)   s:="小米,你好"​   for i, v :=range s{    fmt.Printf("%d %c\n",i,v)   }   }

for 跳从循环

package main​import (    "fmt")func main() {    //for 循环  跳出for循环    // 一、使用break     // 跳过for 循环  continue​    for i:=0; i<10 ; i++{                if i==5{            break        }        fmt.Println("i",i)    }    fmt.Println("over=========")​    for i:=0; i<10 ; i++{        if i==5{            continue        }        fmt.Println("i",i)    }    fmt.Println("over")}

switch

package main​import (    "fmt")func main() {    //switch 循环 ​    var n int=6     switch(n){    case 1:        fmt.Println("=====1======")    case 2:        fmt.Println("=====2======")    case 3:        fmt.Println("=====3======")    case 4:        fmt.Println("=====4======")    case 5:        fmt.Println("=====5=====")    default:        fmt.Println("===========")    }}

package main​import (    "fmt")func main() {    //switch 循环 ​    switch n:=7;n{    case 1,2,3,4:        fmt.Println("=====1======")    case 5:        fmt.Println("=====5=====")    default:        fmt.Println("===========")    }}

package main​import (    "fmt")func main() {    //switch 循环     n:=10    switch {    case n>10:        fmt.Println("=====1======")    case n<=10:        fmt.Println("=====5=====",n)    }}

fallthrough 语句 向下穿一个

数组

数组长度和 类型是 数组一部分

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
	//数组  
	// 存放元素的容器
	//  必须指定存放的元素类型和容量

	var a1 [3] bool
    fmt.Printf("a1:%T",a1)

	//初始化
	//如果不初始化,默认元素是默认值  布尔类型

	// 1、初始化
	a1 =[3]bool{true,true,true}

	fmt.Println("a1",a1)

	//2、初始化2
	// 初始化的值自动推断元素的值
	a4:=[...]int{0,2,3,4}
	fmt.Println("a4", a4)

	//3、初始化
	//根据索引来初始化 数组

	a3:=[5]int{0:1,4:2}
	fmt.Println("a3",a3) 
}

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
	//数组  
	// 存放元素的容器
	//  必须指定存放的元素类型和容量

	var a1 [3] bool
    fmt.Printf("a1:%T",a1)

	//初始化
	//如果不初始化,默认元素是默认值  布尔类型

	// 1、初始化
	a1 =[3]bool{true,true,true}

	fmt.Println("a1",a1)

	//2、初始化2
	// 初始化的值自动推断元素的值
	a4:=[...]int{0,2,3,4}
	fmt.Println("a4", a4)

	//3、初始化
	//根据索引来初始化 数组

	a3:=[5]int{0:1,4:2}
	fmt.Println("a3",a3)

	//数组for 循环 
	//1、根据索引遍历
	for i:=0;i<len(a4);i++{
		fmt.Println(a4[i])
	}
	// 2、 for range 遍历

	for i, v := range a4 {
		fmt.Println(i,v)
	}

	// 多维数组
	var n1 [3][2] int
	n1=[3][2]int{
	{1,2},
    {2,3},
	{3,4},
	}
    fmt.Println(n1)  
}

数组支持 等于 不等于操作

切片

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
	//切片  
	var s1 [] int
	var s2 [] string
	fmt.Println(s1,s2)
	// nil 判断是不是空
	// nil 没有开辟内存空间
	fmt.Println(s1==nil,s2==nil)
   //初始化 

   s1 =[]int{1,2,3}
   s2=[]string{"北京","上海"}
   fmt.Println(s1,s2)
   //长度和容量
   fmt.Println("len",len(s1),len(s2),"cap",cap(s1),cap(s2))

   //由数组得到 切片
   a1 :=[2]int{1,2}
   // 左包含  右不包含  左闭右开
   a2 :=a1[0:1]
   fmt.Println("a1",a2,cap(a2))
   a3 :=a2[:]

   fmt.Printf("%T",a3)
}

make 函数构造切片

切片的本质是一个框,框住了一块连续的内存, 是一个引用类型,底层数据保存在数组中。

切片不能直接比较 是引用类型 当一个切片nil 底层是没有数组 一个nil 的长度和容量都是0 但我们不能认为一个长度和容量都是0的切片一定是nil

判断一个切片是不是空的 一定是len()==0 来判断 不能使用s==nil

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
   // make 函数 创建切片
   // make(类型,长度,容量)
   //  容量 不填默认和长度一致
   s1 := make([]int,5)
   s2 := make ([]int16,10)
   fmt.Println("s1",s1)
   fmt.Println("s2",s2)
   // 索引遍历
   for i:=0;i<len(s1);i++{
      fmt.Println(s1[i])
   }
   // for range 遍历
   for i,v:=range s2{
      fmt.Println(i,v)
   }
}

切片的append()方法

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
   // append() 为切片追加元素
   s1 := []string{"深圳","北京","上海","广州"}

   //s1[5]="李四"  //索引越界
   // 调用append 函数必须用原来的切片变量接收
   s1=append(s1,"李四")
   // append 追加元素,原来的数组 容量不够, cap 换了一个底层数组队
   // 必须使用原来的
   fmt.Println(s1,len(s1),cap(s1))
}

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
   // append() 为切片追加元素
   s1 := []string{"深圳","北京","上海","广州"}

   //s1[5]="李四"  //索引越界
   // 调用append 函数必须用原来的切片变量接收
   s1=append(s1,"李四","小米","小红","小明","雄安")
   // append 追加元素,原来的数组 容量不够, cap 换了一个底层数组队
   // 必须使用原来的
   ss := [] string{"a","d","b"}
   s1=append(s1, ss...)
   fmt.Println(s1,len(s1),cap(s1))
}

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
   // copy(新切片,需要复制的切片)
   s1 := []int{1,2,3}
   s2 :=s1
   var s4=make([]int,3)
   s1[1]=3
   // 引用类型
   copy(s4,s2)
   fmt.Println(s4)
   // 从切片中删除元素
   m1 := [3]int{1,2,3}
   n1 := [] int {1,2,3,4,5,6,7,8,9}
   n1=append(n1[0:1],m1[:]...)
   // 切片不存值 数据存储在底层数组
   n1[1]=7
   fmt.Println(n1)

}

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
   var a=make([]int,5,10)
   // copy(新切片,需要复制的切片)
   fmt.Println(a)
    for i := 0; i < 10; i++ {
       a=append(a,i)
    }

    fmt.Println(a)
    fmt.Println(cap(a))

}

make 和new的区别

1、make和new 都是用于申请内存的

2、new 一般给基本数据类型申请内存 ,基本数据类型返回对应的指针类型

3、 make一般给slice、map、chan 申请内存,make函数返回的是对应的三个个类型本身

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
   //make [keyType]valueType
   var m1 map[int]string 
   // 估计好内存容量  避免动态扩容
   m1=make(map[int]string,10) 
   m1[1]="小米"
   m1[2]="红米"
   // 接收map的值
   v,ok:=m1[3]
   if !ok{
      fmt.Println(v,"ssss")
   }else {
      fmt.Println(v)
   }
}

package main

import (
	"fmt"
)
func main() {
	//复合数据类型
   //make [keyType]valueType
   var m1 map[int]string 
   // 估计好内存容量  避免动态扩容
   m1=make(map[int]string,10) 
   m1[1]="小米"
   m1[2]="红米"
   // 接收map的值
   for k, v := range m1 {
      fmt.Println(k,v)
   }
   // 只遍历 k
   for k:=range m1 {
      fmt.Println(k)
   }
   //只遍历 v
   for _,v:=range m1 {
      fmt.Println(v)
   }
   //删除
   delete(m1,2)
   // 
   delete(m1,3)
   fmt.Println(m1)
}

函数

package main

import (
	"fmt"
)
// 函数定义
// func 函数名(参数名)(返回参数){
     //函数体
//}
func main() {
	sum := sum(1,2,3)
   fmt.Println(sum)
}

// 有参数 有返回值
// 返回值 可以命名  可以不命名
// 不命名 显式返回 
// 命名 不需要  return 返回值  return 不能省略
func sum(x int, y ...int)(ret int){
   ret=x+y[0]
   return
}
// 有参数 没有返回值
func sumx(){
   fmt.Println("大家好。。。。")
}
//多个 返回值

// 参数的类型 简写  两个参数的类型一致 前面的类型简写  
// 可变长参数放最后
func sumy(x,y int) int{
   return x+y
}

// go 没有默认参数

package main

import (
	"fmt"
)
// 函数定义
func main() {
   sum:=sum(1,2,3,4,5,6,7)
   fmt.Println(sum)
}
// 命名函数不能 再命名命名函数
func sum (x int ,y ...int)(sum int) {
   sum=x
   for v:= range y {
   
       sum+=y[v]
   }
  
   return sum
} 

defer 机制

defer 从后到前执行

package main

import (
	"fmt"
)
// 函数定义
func main() {
   sum:=sum(1,2,3,4,5,6,7)
   fmt.Println(sum)
}
// 命名函数不能 再命名命名函数
func sum (x int ,y ...int)(sum int) {
   sum=x
   for v:= range y {
   
       sum+=y[v]
   }

   defer fmt.Println("我执行了。。。。。。")
   defer fmt.Println("。。。。。。。")
  
   return sum
} 

匿名函数

package main

import (
	"fmt"
)
// 函数定义
func main() {
   sum:=sum(1,2,3,4,5,6,7)
   fmt.Println(sum)
}
// 命名函数不能 再命名命名函数
func sum (x int ,y ...int)(sum int) {
   sum=x
   for v:= range y {
   
       sum+=y[v]
   }
   fmt.Println(sum)
   // 返回函数  函数从上到下
   // 匿名函数
   //  func (参数列表)(返回值列表){
       // 函数体
  // }(函数调用)
   // 
   defer func() {
      fmt.Println("dddddd")
      sum+=1
   }()
   
   return sum
} 

全局作用域

package main

import (
	"fmt"
)

var age int=18
// 函数类型以及变量
// 函数也可以作为参数类型传入
// 函数也是类型
func main() {
   // 函数也是类型
   
   m2:=sum(su)
   fmt.Println(m2)
  
}

func sum(x func() int)int {
   age=20
   return x()+3
}
func su() int{
   return 2
}

变量作用域

1、全局作用域

2、函数作用域

1、先在函数内部找变量,找不到再去全局找

2、函数内部的变量,外部访问不到

3、代码块作用域

package main

import (
	"fmt"
)

var age int=18
// 函数类型以及变量
// 函数也可以作为参数类型传入
// 函数也是类型
func main() {
   // 函数也是类型
   m2:=sort(3)
   s()
   fmt.Println(m2)
  
}
func sort(x int) int {
   if x==1{
      return x
   }
   // 立即执行函数
   // 如果只是调用一次的函数  立即执行函数
   func (){
    fmt.Println("大家好。。。。。")
   }()
    return sort(x-1)*x
} 

// 匿名函数  写在函数内部
 var s=func(){
   fmt.Println("dddd")
}

闭包

闭包是一个函数 能包含外部作用域的变量

package main

import (
	"fmt"
)

var age int=18
// 闭包
// 闭包是一个函数  能包含外部作用域的变量
// 底层原理
// 1、函数作为返回值
// 2、函数内部查找变量的顺序,先在自己函数内部找 再从外部找
func f1(f func()){
   fmt.Println("this is f1")
   f()
}

// 闭包
func f2(y int)func(x int) int{
  return func(x int) int {
     return x+y
  }
}

func main(){
   var req= f2(2)(3)
   fmt.Printf("%T",req)
}

panic /recover

package main

import (
	"fmt"
)

var age int=18
// 闭包
// panic /recover  当程序出现错误
func funcA(){
   fmt.Println("A")
}
func funcB(){

   defer func(){
      fmt.Println("ccccccc")
      recover()
   }()
   panic("出现错误了。。。") //程序崩溃退出
   fmt.Println("B")  //不执行。。
}
func funcC(){
   fmt.Println("C")
}

func main(){
   
    funcA()
    funcB()
    funcC()
}

fmt包的

print函数

%T

%t bool类型

%d 十进制

%b 二进制

%x

%0 八进制

%c 字符

%s 字符串

%f 浮点数

%v 值

结构体

自定义类型:

package main

import (
	"fmt"
)

// 自定义类型  和类型别名
// type 后面的类型
type  myInt int
// 类型别名
//  编写中存在  编译后不存在
// rune
type youInt=int

func main(){
   var n myInt=1000
   var m youInt=100
   var c rune
   c='总'
   fmt.Printf("%T\n",n)
   fmt.Printf("%T\n",m)
   fmt.Printf("%T",c)
}

package main

import (
	"fmt"
)

// 自定义类型  和类型别名
// type 后面的类型
type  person struct{
   name string
   age int
   gender string
   address string
}

func main(){
   var p person
   p.name="小米"
   p.age=18
   p.address="北京"
   p.gender="2022-12-20"
   fmt.Println(p)
   fmt.Println(p.name)
}

创建指针类型的结构体

package main

import (
	"fmt"
)

type person struct{
   name string
   age int

}
// 函数传参 永远是副本
func f1(x person){
  x.age=20
}

// 修改值
// 修改内存地址
func f2(x *person){
   (*x).age=20
}

// 匿名结构体
func main(){
  var p person
  p.age=100
  p.name="小明"
  f1(p)
  f2(&p)
  fmt.Println(p)
}

方法

package main

import (
	"fmt"
)

type person struct{
   name string
   age int

}

// 结构体构造函数
// 返回的是结构体还是结构体指针
// 当结构体比较大时 考虑使用结构体指针
func newPerson(name string,age int) *person{
   return &person{
      name: name,
      age: age,
   }
}
// 方法限定接收者
//  func 方法接收者  方法名(参数)返回值{
     // 方法体
//}
func (p person)setName(){
   fmt.Println("大家好。。。。",p.name)
}

// 匿名结构体
func main(){
    p1:=newPerson("小米",18)
    p2:=newPerson("小红",20)
    p1.setName()
    fmt.Println(*p1,*p2)
}

结构体匿名字

默认把类型当成名字

package main

import (
	"fmt"
)

type person struct{
    string
    int
}
// 结构体构造函数
// 返回的是结构体还是结构体指针
// 当结构体比较大时 考虑使用结构体指针
func newPerson(name string,age int) *person{
   return &person{
     string : name,
      int : age,
   }
}
// 方法限定接收者
//  func 方法接收者  方法名(参数)返回值{
     // 方法体
//}
func (p person)setName(){
   fmt.Println("大家好。。。。",p.string)
}

// 匿名结构体
func main(){
    p1:=newPerson("小米",18)
    p2:=newPerson("小红",20)
    p1.setName()
    fmt.Println(*p1,*p2)
}

package main

import (
	"fmt"
)

// 结构体嵌套
type person struct{
   name string
    age int
    addr address
}

type address struct{
    city string
    province string
}

func main(){
    p1:= person{
       name: "xiaomi",
       age: 18,
       addr: address{
          province: "山东",
          city:"实施",
       },
    }
    fmt.Println(p1)
}

匿名嵌套

package main

import (
	"fmt"
)

// 结构体嵌套
type person struct{
   name string
    age int
    address
}

type address struct{
    city string
    province string
}

func main(){
    p1:= person{
       name: "xiaomi",
       age: 18,
       address:address{
          province: "山东",
          city:"实施",
       },
    }
    fmt.Println(p1.city)
}

《JSON》

package main

import (
	"encoding/json"
	"fmt"
)

// 结构体转换为json 的字符串
type anlmal struct{
   Name string `json:"name"`
   Age int `json:"age"`
}
// 序列化
func main(){
    n1:=anlmal{
       Name: "xiaomi",
       Age: 18,
    }
    b,_:=json.Marshal(n1)

    fmt.Println(string(b))
//反序列化
str :=`{"name":"xiaomi","age":18}`
var a anlmal
json.Unmarshal([]byte(str),&a)
fmt.Println(a)
}

时间和 日期相关函数

package main

import (
	"fmt"
	"time"
)

// 结构体转换为json 的字符串
type anlmal struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// 
func main() {
	var tim=time.Now()
	fmt.Println(tim)
	var Year=tim.Year()
	var Month=int(tim.Month())
	var day=tim.Day()
	fmt.Println(Year,Month,day)
    fmt.Print(tim.Format("2006-01-02 15:04:05"))
}

2006-01-02 15:04:05 数值是固定的

时间常量

package main

import (
	"fmt"
	"time"
)

// 结构体转换为json 的字符串
type anlmal struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// 时间常量
const(
   

)
func main() {
	var tim=time.Now()
	for i:=0;i<100;i++{
      fmt.Println(i)
	  time.Sleep(time.Second)
      if(i<100){
		  break
	  }
	}
	//Unix 和 UnixNano 
   fmt.Println(tim.Unix(),tim.UnixNano())
}

单元测试

goroutine

package main

import (
	"fmt"
	"strconv"
	"time"
)

//gorotine
func main() {
  //开启协程
  go test()

  
  for i:=0;i<10;i++{
    fmt.Println("Hello,word==主线程===="+strconv.Itoa(i))
    time.Sleep(time.Second)
  }
}

func test(){
  for i:=0;i<10;i++{
    fmt.Println("Hello,word"+strconv.Itoa(i))
    time.Sleep(time.Second)
  }
}

MPG模式基本介绍

1、M 操作系统的主线程(是物理线程)

2、P:协程执行需要的上下文

3、G:协程

package main

import (
	"fmt"
	"runtime"
)

//gorotine
func main() {
  //开启协程
  num:=runtime.NumCPU()

  fmt.Println("CPU",num)

  //可以设置使用多个CPU
  runtime.SetCPUProfileRate(num-1)

  fmt.Println("ok")
}

共享资源竞争
package main

import (
	"fmt"
	"time"
)

var (
 mymap =make(map[int]int)
)
//gorotine
func main() {
  //开启协程
   for i:=1; i<200;i++{
     go test(i)
   }

   //遍历结果
   time.Sleep(1000*time.Second)
   for i,v:=range mymap {
      fmt.Println(i,v)
   }
}

func test(n int){
   res:=1
  for i := 0; i <=n; i++ {
    res*=i
  }
   mymap[n]=res
  }

package main

import (
	"fmt"
	"sync"
	"time"
	_ "time"
)
var (
  mymap =make(map[int]int , 10)
  lock sync.Mutex
)
//gorotine
func main() {
  //开启协程
   for i:=1; i<70;i++{
     go test(i)
   }

   //遍历结果
   time.Sleep(8*time.Second)
   lock.Lock()
   for i,v:=range mymap {
      fmt.Println(i,v)
   }
   lock.Unlock()
}

func test(n int){
  res:=1
  for i := 1; i <=n; i++ {
    res*=i
  }
  // 加锁
  lock.Lock()
  mymap[n]=res
  //解锁
  defer lock.Unlock()
  }

channel(管道)

队列: 先进先出

channel 引用类型

package main

import (
	"fmt"
)

//channel
func main() {
  var intChan chan int
  intChan=make(chan int,2)
   
  //向管道写数据
  intChan <- 10

  num:=100
  intChan<-num
  // 向管道写入数据时,不能超过其容量
  //  all goroutines are asleep - deadlock!
   //intChan <-10


  //查看管道的长度和容量
  //容量不会自动增长
  fmt.Println(len(intChan),cap(intChan))

  //5.从管道中取数据出来 
  num2:=<-intChan
  fmt.Println(num2)
  fmt.Println(len(intChan),cap(intChan))

  // 没有使用协程 如果没有数据了,会报错
  num3:=<-intChan
  //all goroutines are asleep - deadlock!
  num4:=<-intChan
  fmt.Println(num3,num4)
}

注意事项

package main

import (
	"fmt"
)

type cat struct{
  name string
  age int
}

//channel
func main() {
  
  intChan:=make( chan interface{},10)

  cat1:=cat{
    name: "tome",
    age:18,
  }

  cat2 := cat{
    name: "tome",
    age: 180,
  }

  intChan <- cat1
  intChan <- cat2
  intChan <- "李四"
  intChan <- 10

  num :=<- intChan
  numz:=num.(cat)
  fmt.Printf("%T\n",num)
  fmt.Printf("%v\n",numz.name)

  num3 :=<- intChan
  numx:=num3.(cat)
  fmt.Println(numx.age)
}

channel遍历

package main

import (
	"fmt"
)

type cat struct{
  name string
  age int
}

//channel
func main() {
  intchan :=make(chan interface{},10)
  num :=10
  intchan <- num 
  intchan <- 10 
  intchan <- 20 
  intchan <- 30 
  intchan <- 40 
  intchan <- 50 
  intchan <- 60 
  intchan <- 100
  // close 专门关闭函数的
  close(intchan)
   
  for v := range intchan {
      fmt.Println(v)
  }
}

package main

import (
	"fmt"
)

//channel  只读或者只写 

func main() {
  //读写
   intChen:=make(chan int,20)
   intChen<- 10
   // 声明只读
   var chan2 chan<- int
   chan2=make(chan int,10)
   chan2 <-10
   num :=<- chan2
   defer close(intChen)
   defer close(chan2)
   fmt.Println("大家好。。。。")
}

select

package main

import (
	"fmt"
)

//channel  只读或者只写 

func main() {
  //读写
   intChen:=make(chan int,20)
   for i:=1;i<=10;i++{
     intChen <- i
   }
   //
  stringChan :=make(chan string,20)
  for i:=1; i<=5;i++{
    stringChan <- "hello"+ fmt.Sprintf("%d",i)
  }

  //channel 管道不关闭  没有数据  会
  sdd: for {
    select {
      // 会自动匹配下一个 case
    case v:= <- intChen:
       fmt.Println("从intcha读取数据。。。",v)
    case v:= <- stringChan:
       fmt.Println("从stringChan读取数据。。。",v)
    default:
      fmt.Println("读取不到数据。。。")
      break sdd      
      // return  结束程序
    }
  }
}

package main

import (
	"fmt"
	"time"
)

//channel  只读或者只写
// 协程发生异常
// defer + recover
func main() {
 go sayHello()
 go test()

 for i:=0; i<10 ;i++{
   fmt.Println("Hello WORD")
 }
}

func sayHello(){
  for i:=0;i<10 ;i++{
    time.Sleep(time.Second)
    fmt.Println("hello word")
  }
}

func test(){
  var myMap map[int]string
  defer func ()  {
    if err:=recover(); err !=nil{
      fmt.Println("发生异常了",err)
    }
  }()
  myMap[0]="golang"
}

反射