Let's GO(四)
人生苦短,Let's GO
今天我学了什么?
1.panic && recover
Go的logo是一只萌萌的囊地鼠(Gopher)
当Go程序出现错误,程序将报panic(恐慌)
所以是错误代码吓到小地鼠了吗哈哈
然后需要用recover来安抚它
类似于 try-catch的语法
func b() {
defer func() { //defer must declare before panic
err:=recover() //defer + recover(),recover panic
if err !=nil {
fmt.Println("func b err")
}
}()
panic("panic in func b") //panic 触发结束程序
}
2.goroutine(协程)
非常方便的并发操作,
一个goroutine对应一个函数
func hello() {
fmt.Println("Hello World!")
wg.Done() //goroutine done,count-1
}
//替代time.Sleep(),确保goroutine都执行完毕
var wg sync.WaitGroup
func main() {
wg.Add(1) //count+1
for i := 0; i < 1000; i++ {
wg.Add(1)
go func(i int) {
fmt.Println("hello",i) //形成了闭包,i公用
wg.Done()
}(i)
} //多线程执行数不同
go hello() //open a goroutine
fmt.Println("hello world")
//time.Sleep(time.Second)
wg.Wait() //all goroutine done
}
3.锁
因为不同goroutine可能会同时读写同一个资源,所以需要给资源加锁
a. 互斥锁(sync.Mutex):控制共享资源只被一个goroutine获取
import "sync"
var (
x int
wg. sync.WaitGroup
lock sync.Mutex
)
func add() {
for i := 0; i < 5000; i++ {
lock.Lock() //将x值加锁
x ++
lock.Unlock() //执行完将x的锁取消
}
wg.Done()
}
b.读写互斥锁:适用于读多写少的情况,速度更快。
var (
xx int64
rwlock sync.RWMutex //读写互斥锁
)
func read() {
rwlock.RLock() //加读锁
time.Sleep(time.Millisecond)
rwlock.RUnlock()
wg.Done()
}
func write() {
rwlock.Lock() //写加读写锁
xx = xx + 1
time.Sleep(time.Millisecond*10)
rwlock.Unlock()
wg.Done()
}
4.channel(通道)
Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信。
一个goroutine的值通过channel发送给另一个goroutine
通道FIFO(First in,First out)
//ch1<-
func f1(ch chan<- int) { //(单向通道)chan<- 表示只能发送到通道
for i := 0; i < 100; i++ {
ch <- i
}
close(ch)
}
//( ch2 <- ch1 )^2
func f2(ch1 <-chan int,ch2 chan<- int) { //<-chan 表示只能从通道读取
for {
tmp,ok := <- ch1
if !ok {
break
}
ch2 <- tmp*tmp
}
close(ch2)
}
func main() {
ch1 := make(chan int,100) //初始化通道,100为缓冲区大小
ch2 := make(chan int,200)
go f1(ch1)
go f2(ch1,ch2)
for val := range ch2 {
fmt.Println(val)
}
}
5.网络编程(tcp,udp)
server:1.监听端口 2.建立与client的链接 3.与之交互
client:1.建立与server的链接 2.发送信息 3.关闭连接
//tcp_server_demo
func process(conn net.Conn) {
defer conn.Close() //close connection
//data
for {
reader := bufio.NewReader(conn) //read message
var buf [128]byte
n,err := reader.Read(buf[:])
if err != nil {
fmt.Println("read err,err:",err)
break
}
recv := string(buf[:n])
fmt.Printf("get:%v\n",recv) //show message
conn.Write([]byte("ok")) //reply
}
}
func main() {
//listen
listen,err := net.Listen("tcp","127.0.0.1:20000")
if err != nil {
fmt.Printf("listen port failed,err:%v\n",err)
return
}
//waiting for connection
for {
conn,err := listen.Accept()
if err != nil {
fmt.Printf("accept failed.err:%v\n",err)
continue
}
//go!
go process(conn)
}
}
//tcp_client_demo
func main() {
//conn
conn,err := net.Dial("tcp","127.0.0.1:20000")
if err != nil {
fmt.Println("dial failed,err:",err)
return
}
//send and receiver
input := bufio.NewReader(os.Stdin)
for {
s,_ := input.ReadString('\n')
s = strings.TrimSpace(s)
if strings.ToUpper(s) == "q" { //q for quit
return
}
//send message
_,err := conn.Write([]byte(s))
if err !=nil {
fmt.Printf("send failed,err:%v\n",err)
return
}
//receiver
var buf [1024]byte
n,err := conn.Read(buf[:])
if err != nil {
fmt.Printf("read failed,err:%v\n",err)
return
}
fmt.Println("get reply: ",string(buf[:n]))
}
}
客户端发送,服务端接收并发送反馈信息

这里要先运行server端,不然client端找不到端口会恐慌的
6. 单元测试
执行go test来测试功能是否符合预期
func TestSplit(t *testing.T) { //测试哪个函数就叫Testxxx()
type test struct {
input string
sep string
want []string
}
tests := map[string]test { //给出几组样例,OJ或者leetcode不会就是这样的吧..
"simple":test {"ab c"," ",[]string{"ab","c"}}, //给测试数据命令,可以针对这组数据进行测试
"multi sep":test{"hello,World",",",[]string{"hello","World"}},
}
for name,tc := range tests {
t.Run(name, func(t *testing.T) {
got := Split(tc.input,tc.sep)
if !reflect.DeepEqual(got,tc.want) {
t.Errorf("name:%s want:%v got:%v\n",name,tc.want,got)
}
})
}
}
通过测试:

未能通过测试:

性能测试,将跑够足够的量来测试
//性能基准测试
func BenchmarkSplit(b *testing.B) {
//b.N 由go test决定是否继续加大测试量
for i := 0; i < b.N; i++ {
Split("a,v,c",",")
}
}
将给出详细的测试结果:

总结
Go的基础语法到这里就粗略的过一遍了,如果要打磨自己的基础的,可以从学校OJ一直到acm题多加练习。代码量上去了,理解也会水涨船高。
我可能没有将Go基础语法全部内容写出来,而且我可以说只是复制粘贴稍微整理了一下代码,
更加详细的教学请移步大佬的博客李文周的博客
再次感谢前辈的教学内容。
挺看好Go的前景的,能从Go的各方各面感觉到这个语言的蓬勃生气,
但可能因为还是初学者,眼界不够,暂时也说不出个子丑寅卯来,继续学吧。
人生苦短,GO!GO!GO!
Let's GO(四)的更多相关文章
- 构建一个基本的前端自动化开发环境 —— 基于 Gulp 的前端集成解决方案(四)
通过前面几节的准备工作,对于 npm / node / gulp 应该已经有了基本的认识,本节主要介绍如何构建一个基本的前端自动化开发环境. 下面将逐步构建一个可以自动编译 sass 文件.压缩 ja ...
- 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...
- 如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户
阅读目录 前言 怎么卖 领域服务的使用 回到现实 结语 一.前言 上篇中我们讲述了“把商品卖给用户”中的商品和用户的初步设计.现在把剩余的“卖”这个动作给做了.这里提醒一下,正常情况下,我们的每一步业 ...
- 从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点)
从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www ...
- MVVM设计模式和WPF中的实现(四)事件绑定
MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
- “四核”驱动的“三维”导航 -- 淘宝新UI(需求分析篇)
前言 孔子说:"软件是对客观世界的抽象". 首先声明,这里的"三维导航"和地图没一毛钱关系,"四核驱动"和硬件也没关系,而是为了复杂的应用而 ...
- 【翻译】MongoDB指南/CRUD操作(四)
[原文地址]https://docs.mongodb.com/manual/ CRUD操作(四) 1 查询方案(Query Plans) MongoDB 查询优化程序处理查询并且针对给定可利用的索引选 ...
- HTML 事件(四) 模拟事件操作
本篇主要介绍HTML DOM中事件的模拟操作. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4. ...
- 【原】AFNetworking源码阅读(四)
[原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...
- 带你实现开发者头条APP(四)---首页优化(加入design包)
title: 带你实现开发者头条APP(四)---首页优化(加入design包) tags: design,Toolbar,TabLayout,RecyclerView grammar_cjkRuby ...
随机推荐
- 使用PD(Power Designer)设计数据库,并且生成可执行的SQL文件创建数据库(本文以SQL Server Management Studio软件执行为例)
下载和安装PD: 分享我的软件资源,里面包含了对PD汉化包(链接出问题时可以留言,汉化包只能对软件里面部分菜单栏汉化) 链接:https://pan.baidu.com/s/1lNt1UGZhtDV8 ...
- win10系统无法删除文件的解决方法
方法/步骤 1:首先进入不能删除的文件所在的文件夹 2:右键单击此文件夹,选择授予访问权限 3:在授权界面选择删除权限 4:在删除权限中点击更改共享权限 5:我们选择administrator级别,点 ...
- 油猴脚本 之 网教通直播评论记录抓取 v2.0
先放一个 <油猴脚本 之 网教通直播评论记录抓取>那篇文章的传送门 . 修复内容 将所有表情转为 [符号表情] 字样,而非删除: 修复被禁言用户读取异常,现在被禁言用户表示为 张三 [已禁 ...
- c常用函数-sizeof
sizeof 函数用来返回指定表达式.变量或指定数据类型在内存中所占有的字节数 接下来分析sizeof的计算过程: "abcde"是字符串,考虑到系统自动添加了结束符"\ ...
- json 拼装空list、object
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; public class FastJson ...
- Springboot基于assembly的服务化打包
(1)首先我们编辑 assembly.xml 配置文件,在前文的基础上新增第三方依赖设置(高亮部分),实现将第三方的 jar 包添加到压缩包里的 lib 目录: <?xml version=&q ...
- Oracle调用Java方法(下)复杂Jar包封装成Oracle方法以及ORA-29521错误
上一篇随笔中已经说了简单的Jar是如何封装的,但是我的需求是根据TIPTOP的查询条件产生XML文件并上传到FTP主机中,那么就要涉及到XML生成的方法和FTP上传的方法 所以在Eclipse写的时候 ...
- .NETCore微服务探寻(三) - 分布式日志
前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...
- java SSM框架单元测试最佳实战代码
具体的代码参考链接:https://pan.baidu.com/s/1e9UTyidi4OMBwYydhwH-0g 密码:rmvs 本教程采用的是对单元测试的dao层.service层.control ...
- java scoket Blocking 阻塞IO socket通信四
记住NIO在jdk1.7版本之前是同步非阻塞的,以前的inputsream是同步阻塞的,上面学习完成了Buffer现在我们来学习channel channel书双向的,以前阻塞的io的inputstr ...
