go语法基础二(结构体,协程,锁,xml,io)

package main

import (
   "bytes"
   "encoding/xml"
   "errors"
   "fmt"
   "io/ioutil"
   "log"
   "os"
   "os/user"
   "reflect"
   "runtime"
   "strconv"
   "sync"
   "time"
)

//全局变量
var name,age="jacky",18

func main() {
   //fmt.Println("test main")
   //var b=util.Isempty("abc")
   //fmt.Println(b)
   //util.Hi()
   //
   //fmt.Println(name,age)
   //fmt.Println(util.Name1,util.Age1)
   //
   //f:=closure()
   //fmt.Println(f())
   //fmt.Println(f())
   //fmt.Println(f())

   //a:=6
   //b:="abc"
   slice map channel interface func 是引用类型
   //arr:=[]string{"a","b","c"}
   //c:=100//传指针地址,会修改原先的值
   //testValueAndReference(a,b,arr,&c)
   //
   //fmt.Println(a)
   //fmt.Println(b)
   //fmt.Println(arr)
   //fmt.Println(c)

   //testStrut()

   //p:=People{"figo",18,69}
   //p.run()
   //fmt.Println("跑步后体重",p.Weight)
   //
   //allEat(&p)
   //
   //a:=Animal{"dog",false}
   //allEat(&a)

   //assert()

   //result,e:=testError(18)
   //if result {
   //   fmt.Println("success")
   //}else {
   //   fmt.Println(e.Error())
   //}
   //testDefer()
   //a:=testDeferReturn()
   //fmt.Println("得到返回值a=",a)

   //testPanic()
   //testRecover()

   //testUserInfo()

   //testIO()
   //testReaderAndWriter()
   //testIoUtil()
   //testReflect()

   //testXML()

   //testLog()

   //testSleep()
   //testGoRoutine()
   //testWaitGroup()
   //testMutex
   //testRWMutex()
   //testChannel()
   //testBufferChan()
}
/**
闭包,将局部变量能够返回,
返回的是函数表量
 */
func closure() func() int {
   a:=1
   return func() int {
      a=a+1
      return a
   }
   
}
/**
测试值传递和引用传递
 */
func testValueAndReference(a int,b string,arr []string,c *int)  {
    a=10
    b="test"
    arr[0]="great"
    arr[1]="job"
    *c=123
}
/**
定义接口
 */
type Eat interface {
   eat()
}
/*
People和Animal都实现了eat方法,通过该接口调用实现多态
 */
func allEat(eat Eat)  {
   eat.eat()
}

type People struct {
   Name string
   Age int
   Weight int
}
//方法属于结构体
func( p *People) run()  {
   fmt.Println(p.Name,"当前体重",p.Weight)
   p.Weight=p.Weight-1
}
/**
实现接口Eat中的eat方法
 */
func( p *People) eat()  {
   fmt.Println(p.Name,"正在吃饭")

}

type Animal struct {
   Name string
   CanFly bool
}
/**
动物也实现接口Eat中的eat方法
 */
func(a *Animal) eat()  {
   fmt.Println(a.Name,"正在吃饭")
}
/**
测试结构体
 */
func testStrut()  {
   peo1:=People{"andy",18,69}
   peo2:=People{Age: 16,Name: "anna"}
   fmt.Printf("%p\n",&peo1)
   fmt.Printf("%p\n",&peo2)
   fmt.Println(peo1)
   fmt.Println(peo2)
   peo1.Name="jacky"
   fmt.Println(peo1)
   var peo3 People
   peo3=peo1
   //结构体是值类型,这里虽然改变了name但是peo1不受影响
   peo3.Name="tom"
   fmt.Println("peo1=",peo1)
   fmt.Println("peo3=",peo3)


   //结构体指针
   peo5:=new(People)
   peo5.Name="rose"
   peo5.Age=15
   fmt.Println("peo5",peo5)

   peo6:=&People{"figo",18,66}
   fmt.Println("peo6",peo6)
   fmt.Println(peo5==peo6)

   //因为定义的是指针,所以修改后peo5会跟着改变
   peo7:=peo5
   peo7.Name="mary"
   fmt.Println("peo5",peo5)
   fmt.Println("peo7",peo7)
   fmt.Println(peo5==peo7)

}
/**
断言
 */
func assert()  {
   var i interface{}=123
   //断言是否是int,是返回值给result,ok接收断言是否准确,当为false时,result会赋默认值
   result,ok:=i.(int)
   fmt.Println(result,ok)

   result1,ok1:=i.(float64)
   fmt.Println(result1,ok1)
}
/**
测试返回error
 */
func testError(age int)(result bool,e error)  {
    if age<18 {
       result=false
       //e=errors.New("年龄小于18岁,不宜观看")
       //两种定义都可以
       e=fmt.Errorf("年龄%d,小于18岁,不易观看",age)
       return
    }else {
       result=true
       e=errors.New("年龄大于等于18岁,宜观看")
       return
    }
}
/**
defer推迟执行
顺序是 A C E D B
defer函数是放入栈中,先进后出
 */

func testDefer()  {
   fmt.Println("执行步骤A")
   defer func() {
      fmt.Println("推迟执行步骤B")
   }()
   fmt.Println("执行步骤C")
   defer func() {
      fmt.Println("推迟执行步骤D")
   }()
   fmt.Println("执行步骤E")
}
/**
延迟执行带返回值
如果这里不定义r变量,那么返回的a将等于19,定义了
返回是20
 */
func testDeferReturn() (r int)  {
   a:=18
   fmt.Println("执行步骤A,a=",a)
   defer func() {
      //这么写是19
      //a++
      //这么写是20
      r=a+1
      fmt.Println("执行步骤B,r=",r)
   }()
   a++
   fmt.Println("执行步骤C,a=",a)
   return a
   //定义了r,可以直接写return
   //return
}
/**
测试异常抛出,相当于java的throw
 */
func testPanic()  {
   fmt.Println("test")
   defer func() {
      fmt.Println("抛出异常后,这里还是会被执行的")
   }()
   panic("抛出异常")
   fmt.Println("这里不会被执行")

}
/**
测试从异常中恢复recover()函数,用于捕获异常
然后从异常中恢复
 */
func testRecover()  {
   fmt.Println("start")
   defer func() {
      if err:=recover();err!=nil{
         fmt.Println("出现异常",err)
         fmt.Println("继续执行其他逻辑")
      }
   }()
   panic("抛出异常测试")
}
/**
获取计算机用户信息
 */
func testUserInfo()  {
   u,e:=user.Current()
   if e!=nil{
      fmt.Println(e)
      return
   }
   fmt.Println(u.Uid)
   fmt.Println(u.Gid)
   fmt.Println(u.Name)
   fmt.Println(u.HomeDir)

}
/**
文件或文件夹增删改查测试
 */
func testIO()  {
   //创建文件夹 test文件夹必须存在否则报错
   //err:=os.Mkdir("E:\\test1\\gotest",os.ModeDir)
   //if err!=nil{
   //   fmt.Println(err)
   //   return
   //}
   //fmt.Println("文件夹创建成功")

   //创建文件夹 test文件夹不存在也可以成功
   //err1:=os.MkdirAll("E:\\test1\\gotest",os.ModeDir)
   //if err1!=nil{
   //   fmt.Println(err1)
   //   return
   //}
   //fmt.Println("文件夹创建成功")

   //创建文件
   //f,err:=os.Create("E:\\test\\gotest\\test.txt")
   //if err!=nil {
   //     fmt.Println(err)
   //     return
   //}
   //fmt.Println("文件创建成功,文件名=",f.Name())
   //文件夹重命名,gotest文件夹下必须没有文件,否则无法重命名
   //err1:=os.Rename("E:\\test\\gotest","E:\\test\\gotestnew")
   //if err1!=nil {
   //   fmt.Println(err1)
   //   return
   //}

   //读取文件
   //f,err:=os.Open("E:\\test\\gotestnew\\新建文本文档.txt")
   //if err!=nil {
   //  fmt.Println(err)
   //  return
   //}
   //fi,e:=f.Stat()
   //if e!=nil {
   //   fmt.Println(e)
   //   return
   //}
   //fmt.Println(fi.Name(),fi.Size(),fi.IsDir(),fi.Mode())


   //删除文件或文件夹,文件或文件夹必须存在,否则报错
   //e:=os.Remove("E:\\test\\gotestnew\\新建文本文档.txt")
   //if e!=nil {
   // fmt.Println("删除失败",e)
   // return
   //}
   //fmt.Println("删除成功")

   //文件或文件夹不存在也不会报错
   //e1:=os.RemoveAll("E:\\test\\gotestnew")
   //if e1!=nil {
   //  fmt.Println("删除失败",e1)
   //  return
   //}
   //fmt.Println("删除成功")


   testReflect()
}
/**
输入输出流测试
 */
func testReaderAndWriter()  {
   //打开文件open,只读
   //f,e:=os.Open("E:\\test\\gotestnew\\test.txt")
   //openFile可读可写
   f,e:=os.OpenFile("E:\\test\\gotestnew\\test.txt",os.O_APPEND,0660)

   if e!=nil{
      fmt.Println("读取文件失败",e)
      return
   }
   //获取fileinfo信息
   fi,er:=f.Stat()
   if er!=nil{
      fmt.Println("读取文件失败",er)
      //return
      //不存在则创建
      os.Create("E:\\test\\gotestnew\\test.txt")
   }
   b:=make([]byte,fi.Size())
   //输入流,读取
   f.Read(b)
   v:=string(b)
   fmt.Println("读取到的值=",v)
   //输出流,写入
   f.Write([]byte("\r\n hello,world!"))
   f.WriteString("great")//内部是write

}
/**
测试ioutil
 */
func testIoUtil()  {
   //读取file,e用_表示不处理
   //f,_:=os.Open("E:\\test\\gotestnew\\test.txt")
   //b,_:=ioutil.ReadAll(f)
   //fmt.Println(string(b))

   //直接读取,这里是定义变量需要加:,否则使用var 和变量类型
   b,_:=ioutil.ReadFile("E:\\test\\gotestnew\\test.txt")
   fmt.Println(string(b))

   ioutil.WriteFile("E:\\test\\gotestnew\\test.txt",[]byte("\r\n这里是写入的新数据"),0666)
   //这里是赋值,不需要加:
   b,_=ioutil.ReadFile("E:\\test\\gotestnew\\test.txt")
   fmt.Println(string(b))

   //读取文件夹
   fileArr,e:=ioutil.ReadDir("E:\\test\\gotestnew\\")
   if e!=nil{
      fmt.Println(e)
   }
   for _,f:=range fileArr{
      fmt.Println(f.Name(),f.Size(),f.Mode(),f.IsDir(),f.ModTime())
   }

   str := "abc"
   //通过for打印每个字符
   fmt.Println("-----循环第一种用法------")
   for i := 0; i < len(str); i++ {
      fmt.Printf("str[%d]=%c\n", i, str[i])
   }
   fmt.Println("-----循环第二种用法------")

   for i := range str { //第2个返回值,默认丢弃,返回元素的位置(下标)
      fmt.Printf("str[%d]=%c\n", i, str[i])
   }
   fmt.Println("-----循环第二种用法,两个参数,第一个是索引,第二个是值------")

   for _, item := range str { //第2个返回值,默认丢弃,返回元素的位置(下标)
      fmt.Printf("%c\n",item)
   }

}
type Student struct {
   Name string
   Age int
}
/**
测试反射
 */
func testReflect(){
   //s:=Student{"andy",18}
   s:=new(Student)
   s.Name="rose"
   s.Age=18
   fmt.Println(reflect.TypeOf(s))
   fmt.Println(reflect.ValueOf(s))
}

/**
测试XML读取
 */
type Person struct {
   XMLName xml.Name `xml:"person"`
   Id int `xml:"id,attr"`
   Name string  `xml:"name"`
   Address string `xml:"address"`

}

func testXML()  {
   //读取xml
   peo:=new(Person)
   b,_:=ioutil.ReadFile("person.xml")
   fmt.Println(string(b))
   xml.Unmarshal(b,peo)
   fmt.Println(peo)

   //生成xml
   p1:=Person{Id:1,Name:"jacky",Address: "sh"}
   b1,_:=xml.MarshalIndent(p1,"","  ")
   b2:=append([]byte(xml.Header),b1...)
   ioutil.WriteFile("E:\\test\\gotestnew\\person.xml",b2,0666)



}
/**
测试日志打印
 */
func testLog()  {
   f,e:=os.OpenFile("E:\\test\\gotestnew\\log.txt",os.O_APPEND|os.O_CREATE,0777)
   if e!=nil{
     fmt.Println(e)
   }
   logger:=log.New(f,"[info]",log.LstdFlags)
   logger.Println("打印日志测试")

}
/**
测试线程睡眠
 */
func testSleep()  {
     fmt.Println("程序开始")
     time.Sleep(2e9)//单位纳秒 这里表示2秒
     time.AfterFunc(2e9, func() {
        fmt.Println("2秒后,开始执行这里")
     })
     //主协程这里睡眠一下,不然看不到另外一个协程的执行结果
     time.Sleep(3e9)
     fmt.Println("程序执行结束")

   
}

/**
协程测试
 */
func testGoRoutine()  {
   for i:=1;i<10;i++{
      go testGo()
   }
   //主协程睡眠一会,免得看不到子协程打印日志
   time.Sleep(3e9)
}
func testGo()  {
   for i:=1;i<10;i++{
      fmt.Println("当前协程编号",goID())
      fmt.Println("当前值=",i)
   }
}
/**
获取协程编号
 */
func goID() uint64 {
   b := make([]byte, 64)
   b = b[:runtime.Stack(b, false)]
   b = bytes.TrimPrefix(b, []byte("goroutine "))
   b = b[:bytes.IndexByte(b, ' ')]
   n, _ := strconv.ParseUint(string(b), 10, 64)
   return n
}

/**
测试计数器WaitGroup,相当于java里面的countdownlatch
 */
func testWaitGroup()  {
   var wg sync.WaitGroup
   wg.Add(10)
   for i:=0;i<10;i++{
      go func() {
         fmt.Println(i)
         wg.Done()
      }()
   }
   wg.Wait()
   fmt.Println("执行完成")
}

/**
测试互斥锁与读写锁
 */
var(
   num=100
   wg sync.WaitGroup
   m sync.Mutex
)
func testMutex()  {
   //wg.Add(1000)
   for i:=0;i<1000;i++{
      go deductStock()

   }
   //不加锁库存会变成-1
   //wg.Wait()
   fmt.Println("剩余库存=",num)
}
/**
扣减库存,加互斥锁(分布式环境无效,单机环境可以)
 */
func deductStock()  {
   m.Lock()
   if num>0{
      num=num-1
   }
   m.Unlock()
   //wg.Done()

}
/**
测试读写互斥锁
 */
func testRWMutex()  {
   var rwm sync.RWMutex
   var wg sync.WaitGroup
   wg.Add(100)
   m:=make(map[int]int)
   for i:=0;i<100;i++{
      go func(j int) {
         rwm.Lock()
         //又读又写,就有可能报出:fatal error: concurrent map writes
         m[i]=j
         fmt.Println(m)
         rwm.Unlock()
         wg.Done()
      }(i)
   }
   wg.Wait()
   fmt.Println("多协程执行完成")
}
/**
协程间通信用chan,chan在读写的时候都会阻塞
 */
func testChannel(){
   ch:=make(chan int)

   
   go func() {
      fmt.Println("子协程执行开始后,阻塞在这里等等获取ch里面的数据")
      ch<-100
      fmt.Println("子协程执行结束")


   }()

   //go func() {
   //   fmt.Println("开始去ch里面的数据")
   //   a:=<-ch
   //   fmt.Println("取完ch里面的数据了",a)
   //
   //}()
   fmt.Println("主协程开始读取")
   a:=<-ch
   fmt.Println("主协程执行完成",a)
}

func testBufferChan()  {
   ch:=make(chan int,3)
   ch<-1
   ch<-1
   ch<-1
   //超出个数就会阻塞,除非往外取一个<-ch
   //ch<-1

   fmt.Println("程序运行结束")
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值