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("程序运行结束")
}
go语法基础二(结构体,协程,锁,xml,io)
最新推荐文章于 2023-06-05 16:27:12 发布