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


    1. package main
    2. import (
    3. "bytes"
    4. "encoding/xml"
    5. "errors"
    6. "fmt"
    7. "io/ioutil"
    8. "log"
    9. "os"
    10. "os/user"
    11. "reflect"
    12. "runtime"
    13. "strconv"
    14. "sync"
    15. "time"
    16. )
    17. //全局变量
    18. var name,age="jacky",18
    19. func main() {
    20. //fmt.Println("test main")
    21. //var b=util.Isempty("abc")
    22. //fmt.Println(b)
    23. //util.Hi()
    24. //
    25. //fmt.Println(name,age)
    26. //fmt.Println(util.Name1,util.Age1)
    27. //
    28. //f:=closure()
    29. //fmt.Println(f())
    30. //fmt.Println(f())
    31. //fmt.Println(f())
    32. //a:=6
    33. //b:="abc"
    34. slice map channel interface func 是引用类型
    35. //arr:=[]string{"a","b","c"}
    36. //c:=100//传指针地址,会修改原先的值
    37. //testValueAndReference(a,b,arr,&c)
    38. //
    39. //fmt.Println(a)
    40. //fmt.Println(b)
    41. //fmt.Println(arr)
    42. //fmt.Println(c)
    43. //testStrut()
    44. //p:=People{"figo",18,69}
    45. //p.run()
    46. //fmt.Println("跑步后体重",p.Weight)
    47. //
    48. //allEat(&p)
    49. //
    50. //a:=Animal{"dog",false}
    51. //allEat(&a)
    52. //assert()
    53. //result,e:=testError(18)
    54. //if result {
    55. // fmt.Println("success")
    56. //}else {
    57. // fmt.Println(e.Error())
    58. //}
    59. //testDefer()
    60. //a:=testDeferReturn()
    61. //fmt.Println("得到返回值a=",a)
    62. //testPanic()
    63. //testRecover()
    64. //testUserInfo()
    65. //testIO()
    66. //testReaderAndWriter()
    67. //testIoUtil()
    68. //testReflect()
    69. //testXML()
    70. //testLog()
    71. //testSleep()
    72. //testGoRoutine()
    73. //testWaitGroup()
    74. //testMutex
    75. //testRWMutex()
    76. //testChannel()
    77. //testBufferChan()
    78. }
    79. /**
    80. 闭包,将局部变量能够返回,
    81. 返回的是函数表量
    82. */
    83. func closure() func() int {
    84. a:=1
    85. return func() int {
    86. a=a+1
    87. return a
    88. }
    89. }
    90. /**
    91. 测试值传递和引用传递
    92. */
    93. func testValueAndReference(a int,b string,arr []string,c *int) {
    94. a=10
    95. b="test"
    96. arr[0]="great"
    97. arr[1]="job"
    98. *c=123
    99. }
    100. /**
    101. 定义接口
    102. */
    103. type Eat interface {
    104. eat()
    105. }
    106. /*
    107. People和Animal都实现了eat方法,通过该接口调用实现多态
    108. */
    109. func allEat(eat Eat) {
    110. eat.eat()
    111. }
    112. type People struct {
    113. Name string
    114. Age int
    115. Weight int
    116. }
    117. //方法属于结构体
    118. func( p *People) run() {
    119. fmt.Println(p.Name,"当前体重",p.Weight)
    120. p.Weight=p.Weight-1
    121. }
    122. /**
    123. 实现接口Eat中的eat方法
    124. */
    125. func( p *People) eat() {
    126. fmt.Println(p.Name,"正在吃饭")
    127. }
    128. type Animal struct {
    129. Name string
    130. CanFly bool
    131. }
    132. /**
    133. 动物也实现接口Eat中的eat方法
    134. */
    135. func(a *Animal) eat() {
    136. fmt.Println(a.Name,"正在吃饭")
    137. }
    138. /**
    139. 测试结构体
    140. */
    141. func testStrut() {
    142. peo1:=People{"andy",18,69}
    143. peo2:=People{Age: 16,Name: "anna"}
    144. fmt.Printf("%p\n",&peo1)
    145. fmt.Printf("%p\n",&peo2)
    146. fmt.Println(peo1)
    147. fmt.Println(peo2)
    148. peo1.Name="jacky"
    149. fmt.Println(peo1)
    150. var peo3 People
    151. peo3=peo1
    152. //结构体是值类型,这里虽然改变了name但是peo1不受影响
    153. peo3.Name="tom"
    154. fmt.Println("peo1=",peo1)
    155. fmt.Println("peo3=",peo3)
    156. //结构体指针
    157. peo5:=new(People)
    158. peo5.Name="rose"
    159. peo5.Age=15
    160. fmt.Println("peo5",peo5)
    161. peo6:=&People{"figo",18,66}
    162. fmt.Println("peo6",peo6)
    163. fmt.Println(peo5==peo6)
    164. //因为定义的是指针,所以修改后peo5会跟着改变
    165. peo7:=peo5
    166. peo7.Name="mary"
    167. fmt.Println("peo5",peo5)
    168. fmt.Println("peo7",peo7)
    169. fmt.Println(peo5==peo7)
    170. }
    171. /**
    172. 断言
    173. */
    174. func assert() {
    175. var i interface{}=123
    176. //断言是否是int,是返回值给result,ok接收断言是否准确,当为false时,result会赋默认值
    177. result,ok:=i.(int)
    178. fmt.Println(result,ok)
    179. result1,ok1:=i.(float64)
    180. fmt.Println(result1,ok1)
    181. }
    182. /**
    183. 测试返回error
    184. */
    185. func testError(age int)(result bool,e error) {
    186. if age<18 {
    187. result=false
    188. //e=errors.New("年龄小于18岁,不宜观看")
    189. //两种定义都可以
    190. e=fmt.Errorf("年龄%d,小于18岁,不易观看",age)
    191. return
    192. }else {
    193. result=true
    194. e=errors.New("年龄大于等于18岁,宜观看")
    195. return
    196. }
    197. }
    198. /**
    199. defer推迟执行
    200. 顺序是 A C E D B
    201. defer函数是放入栈中,先进后出
    202. */
    203. func testDefer() {
    204. fmt.Println("执行步骤A")
    205. defer func() {
    206. fmt.Println("推迟执行步骤B")
    207. }()
    208. fmt.Println("执行步骤C")
    209. defer func() {
    210. fmt.Println("推迟执行步骤D")
    211. }()
    212. fmt.Println("执行步骤E")
    213. }
    214. /**
    215. 延迟执行带返回值
    216. 如果这里不定义r变量,那么返回的a将等于19,定义了
    217. 返回是20
    218. */
    219. func testDeferReturn() (r int) {
    220. a:=18
    221. fmt.Println("执行步骤A,a=",a)
    222. defer func() {
    223. //这么写是19
    224. //a++
    225. //这么写是20
    226. r=a+1
    227. fmt.Println("执行步骤B,r=",r)
    228. }()
    229. a++
    230. fmt.Println("执行步骤C,a=",a)
    231. return a
    232. //定义了r,可以直接写return
    233. //return
    234. }
    235. /**
    236. 测试异常抛出,相当于java的throw
    237. */
    238. func testPanic() {
    239. fmt.Println("test")
    240. defer func() {
    241. fmt.Println("抛出异常后,这里还是会被执行的")
    242. }()
    243. panic("抛出异常")
    244. fmt.Println("这里不会被执行")
    245. }
    246. /**
    247. 测试从异常中恢复recover()函数,用于捕获异常
    248. 然后从异常中恢复
    249. */
    250. func testRecover() {
    251. fmt.Println("start")
    252. defer func() {
    253. if err:=recover();err!=nil{
    254. fmt.Println("出现异常",err)
    255. fmt.Println("继续执行其他逻辑")
    256. }
    257. }()
    258. panic("抛出异常测试")
    259. }
    260. /**
    261. 获取计算机用户信息
    262. */
    263. func testUserInfo() {
    264. u,e:=user.Current()
    265. if e!=nil{
    266. fmt.Println(e)
    267. return
    268. }
    269. fmt.Println(u.Uid)
    270. fmt.Println(u.Gid)
    271. fmt.Println(u.Name)
    272. fmt.Println(u.HomeDir)
    273. }
    274. /**
    275. 文件或文件夹增删改查测试
    276. */
    277. func testIO() {
    278. //创建文件夹 test文件夹必须存在否则报错
    279. //err:=os.Mkdir("E:\\test1\\gotest",os.ModeDir)
    280. //if err!=nil{
    281. // fmt.Println(err)
    282. // return
    283. //}
    284. //fmt.Println("文件夹创建成功")
    285. //创建文件夹 test文件夹不存在也可以成功
    286. //err1:=os.MkdirAll("E:\\test1\\gotest",os.ModeDir)
    287. //if err1!=nil{
    288. // fmt.Println(err1)
    289. // return
    290. //}
    291. //fmt.Println("文件夹创建成功")
    292. //创建文件
    293. //f,err:=os.Create("E:\\test\\gotest\\test.txt")
    294. //if err!=nil {
    295. // fmt.Println(err)
    296. // return
    297. //}
    298. //fmt.Println("文件创建成功,文件名=",f.Name())
    299. //文件夹重命名,gotest文件夹下必须没有文件,否则无法重命名
    300. //err1:=os.Rename("E:\\test\\gotest","E:\\test\\gotestnew")
    301. //if err1!=nil {
    302. // fmt.Println(err1)
    303. // return
    304. //}
    305. //读取文件
    306. //f,err:=os.Open("E:\\test\\gotestnew\\新建文本文档.txt")
    307. //if err!=nil {
    308. // fmt.Println(err)
    309. // return
    310. //}
    311. //fi,e:=f.Stat()
    312. //if e!=nil {
    313. // fmt.Println(e)
    314. // return
    315. //}
    316. //fmt.Println(fi.Name(),fi.Size(),fi.IsDir(),fi.Mode())
    317. //删除文件或文件夹,文件或文件夹必须存在,否则报错
    318. //e:=os.Remove("E:\\test\\gotestnew\\新建文本文档.txt")
    319. //if e!=nil {
    320. // fmt.Println("删除失败",e)
    321. // return
    322. //}
    323. //fmt.Println("删除成功")
    324. //文件或文件夹不存在也不会报错
    325. //e1:=os.RemoveAll("E:\\test\\gotestnew")
    326. //if e1!=nil {
    327. // fmt.Println("删除失败",e1)
    328. // return
    329. //}
    330. //fmt.Println("删除成功")
    331. testReflect()
    332. }
    333. /**
    334. 输入输出流测试
    335. */
    336. func testReaderAndWriter() {
    337. //打开文件open,只读
    338. //f,e:=os.Open("E:\\test\\gotestnew\\test.txt")
    339. //openFile可读可写
    340. f,e:=os.OpenFile("E:\\test\\gotestnew\\test.txt",os.O_APPEND,0660)
    341. if e!=nil{
    342. fmt.Println("读取文件失败",e)
    343. return
    344. }
    345. //获取fileinfo信息
    346. fi,er:=f.Stat()
    347. if er!=nil{
    348. fmt.Println("读取文件失败",er)
    349. //return
    350. //不存在则创建
    351. os.Create("E:\\test\\gotestnew\\test.txt")
    352. }
    353. b:=make([]byte,fi.Size())
    354. //输入流,读取
    355. f.Read(b)
    356. v:=string(b)
    357. fmt.Println("读取到的值=",v)
    358. //输出流,写入
    359. f.Write([]byte("\r\n hello,world!"))
    360. f.WriteString("great")//内部是write
    361. }
    362. /**
    363. 测试ioutil
    364. */
    365. func testIoUtil() {
    366. //读取file,e用_表示不处理
    367. //f,_:=os.Open("E:\\test\\gotestnew\\test.txt")
    368. //b,_:=ioutil.ReadAll(f)
    369. //fmt.Println(string(b))
    370. //直接读取,这里是定义变量需要加:,否则使用var 和变量类型
    371. b,_:=ioutil.ReadFile("E:\\test\\gotestnew\\test.txt")
    372. fmt.Println(string(b))
    373. ioutil.WriteFile("E:\\test\\gotestnew\\test.txt",[]byte("\r\n这里是写入的新数据"),0666)
    374. //这里是赋值,不需要加:
    375. b,_=ioutil.ReadFile("E:\\test\\gotestnew\\test.txt")
    376. fmt.Println(string(b))
    377. //读取文件夹
    378. fileArr,e:=ioutil.ReadDir("E:\\test\\gotestnew\\")
    379. if e!=nil{
    380. fmt.Println(e)
    381. }
    382. for _,f:=range fileArr{
    383. fmt.Println(f.Name(),f.Size(),f.Mode(),f.IsDir(),f.ModTime())
    384. }
    385. str := "abc"
    386. //通过for打印每个字符
    387. fmt.Println("-----循环第一种用法------")
    388. for i := 0; i < len(str); i++ {
    389. fmt.Printf("str[%d]=%c\n", i, str[i])
    390. }
    391. fmt.Println("-----循环第二种用法------")
    392. for i := range str { //第2个返回值,默认丢弃,返回元素的位置(下标)
    393. fmt.Printf("str[%d]=%c\n", i, str[i])
    394. }
    395. fmt.Println("-----循环第二种用法,两个参数,第一个是索引,第二个是值------")
    396. for _, item := range str { //第2个返回值,默认丢弃,返回元素的位置(下标)
    397. fmt.Printf("%c\n",item)
    398. }
    399. }
    400. type Student struct {
    401. Name string
    402. Age int
    403. }
    404. /**
    405. 测试反射
    406. */
    407. func testReflect(){
    408. //s:=Student{"andy",18}
    409. s:=new(Student)
    410. s.Name="rose"
    411. s.Age=18
    412. fmt.Println(reflect.TypeOf(s))
    413. fmt.Println(reflect.ValueOf(s))
    414. }
    415. /**
    416. 测试XML读取
    417. */
    418. type Person struct {
    419. XMLName xml.Name `xml:"person"`
    420. Id int `xml:"id,attr"`
    421. Name string `xml:"name"`
    422. Address string `xml:"address"`
    423. }
    424. func testXML() {
    425. //读取xml
    426. peo:=new(Person)
    427. b,_:=ioutil.ReadFile("person.xml")
    428. fmt.Println(string(b))
    429. xml.Unmarshal(b,peo)
    430. fmt.Println(peo)
    431. //生成xml
    432. p1:=Person{Id:1,Name:"jacky",Address: "sh"}
    433. b1,_:=xml.MarshalIndent(p1,""," ")
    434. b2:=append([]byte(xml.Header),b1...)
    435. ioutil.WriteFile("E:\\test\\gotestnew\\person.xml",b2,0666)
    436. }
    437. /**
    438. 测试日志打印
    439. */
    440. func testLog() {
    441. f,e:=os.OpenFile("E:\\test\\gotestnew\\log.txt",os.O_APPEND|os.O_CREATE,0777)
    442. if e!=nil{
    443. fmt.Println(e)
    444. }
    445. logger:=log.New(f,"[info]",log.LstdFlags)
    446. logger.Println("打印日志测试")
    447. }
    448. /**
    449. 测试线程睡眠
    450. */
    451. func testSleep() {
    452. fmt.Println("程序开始")
    453. time.Sleep(2e9)//单位纳秒 这里表示2秒
    454. time.AfterFunc(2e9, func() {
    455. fmt.Println("2秒后,开始执行这里")
    456. })
    457. //主协程这里睡眠一下,不然看不到另外一个协程的执行结果
    458. time.Sleep(3e9)
    459. fmt.Println("程序执行结束")
    460. }
    461. /**
    462. 协程测试
    463. */
    464. func testGoRoutine() {
    465. for i:=1;i<10;i++{
    466. go testGo()
    467. }
    468. //主协程睡眠一会,免得看不到子协程打印日志
    469. time.Sleep(3e9)
    470. }
    471. func testGo() {
    472. for i:=1;i<10;i++{
    473. fmt.Println("当前协程编号",goID())
    474. fmt.Println("当前值=",i)
    475. }
    476. }
    477. /**
    478. 获取协程编号
    479. */
    480. func goID() uint64 {
    481. b := make([]byte, 64)
    482. b = b[:runtime.Stack(b, false)]
    483. b = bytes.TrimPrefix(b, []byte("goroutine "))
    484. b = b[:bytes.IndexByte(b, ' ')]
    485. n, _ := strconv.ParseUint(string(b), 10, 64)
    486. return n
    487. }
    488. /**
    489. 测试计数器WaitGroup,相当于java里面的countdownlatch
    490. */
    491. func testWaitGroup() {
    492. var wg sync.WaitGroup
    493. wg.Add(10)
    494. for i:=0;i<10;i++{
    495. go func() {
    496. fmt.Println(i)
    497. wg.Done()
    498. }()
    499. }
    500. wg.Wait()
    501. fmt.Println("执行完成")
    502. }
    503. /**
    504. 测试互斥锁与读写锁
    505. */
    506. var(
    507. num=100
    508. wg sync.WaitGroup
    509. m sync.Mutex
    510. )
    511. func testMutex() {
    512. //wg.Add(1000)
    513. for i:=0;i<1000;i++{
    514. go deductStock()
    515. }
    516. //不加锁库存会变成-1
    517. //wg.Wait()
    518. fmt.Println("剩余库存=",num)
    519. }
    520. /**
    521. 扣减库存,加互斥锁(分布式环境无效,单机环境可以)
    522. */
    523. func deductStock() {
    524. m.Lock()
    525. if num>0{
    526. num=num-1
    527. }
    528. m.Unlock()
    529. //wg.Done()
    530. }
    531. /**
    532. 测试读写互斥锁
    533. */
    534. func testRWMutex() {
    535. var rwm sync.RWMutex
    536. var wg sync.WaitGroup
    537. wg.Add(100)
    538. m:=make(map[int]int)
    539. for i:=0;i<100;i++{
    540. go func(j int) {
    541. rwm.Lock()
    542. //又读又写,就有可能报出:fatal error: concurrent map writes
    543. m[i]=j
    544. fmt.Println(m)
    545. rwm.Unlock()
    546. wg.Done()
    547. }(i)
    548. }
    549. wg.Wait()
    550. fmt.Println("多协程执行完成")
    551. }
    552. /**
    553. 协程间通信用chan,chan在读写的时候都会阻塞
    554. */
    555. func testChannel(){
    556. ch:=make(chan int)
    557. go func() {
    558. fmt.Println("子协程执行开始后,阻塞在这里等等获取ch里面的数据")
    559. ch<-100
    560. fmt.Println("子协程执行结束")
    561. }()
    562. //go func() {
    563. // fmt.Println("开始去ch里面的数据")
    564. // a:=<-ch
    565. // fmt.Println("取完ch里面的数据了",a)
    566. //
    567. //}()
    568. fmt.Println("主协程开始读取")
    569. a:=<-ch
    570. fmt.Println("主协程执行完成",a)
    571. }
    572. func testBufferChan() {
    573. ch:=make(chan int,3)
    574. ch<-1
    575. ch<-1
    576. ch<-1
    577. //超出个数就会阻塞,除非往外取一个<-ch
    578. //ch<-1
    579. fmt.Println("程序运行结束")
    580. }

  • 相关阅读:
    [网鼎杯 2020 朱雀组]Nmap 通过nmap写入木马 argcmd过滤实现逃逸
    ChatGPT Prompting开发实战(十一)
    Word | 简单可操作的快捷公式编号、右对齐和引用方法
    DigestUtils实现md5加密算法
    【技术分享】EIGRP stub实验
    【LeetCode】Day183-数组的均值分割
    如何使用 Kubernetes Hooks 跟踪容器生命周期
    Git的安装和使用以及VScode配置Git的快速使用
    一个简单的HTML篮球网页【学生网页设计作业源码】
    如何弄懂复杂项目
  • 原文地址:https://blog.csdn.net/figo0423/article/details/126398462