Golang walkthrough: io package

Golang walkthrough: io package Go是用于处理字节的编程语言。 无论您有字节列表,字节流还是单个字节,Go都可以轻松处理。 从这些简单的原语,我们构建了我们的抽象和服务。 io包是标准库中最基础的包之一。 它提供了一组用于处理字节流的接口和助手。 这篇文章是一系列演练的一部分,可以帮助您更好地了解标准库。 虽然官方的文档提供了大量的信息,但是在现实世界的环境中还是很难理解库的意思。 本系列旨在提供如何在每天应用程序中使用标准库包的上下文。 如果您有任何问题或意见,可以在Twitter上的@benbjohnson与我联系。(当然也可以联系我,listomebao@gmail.com) Reading bytes 字节有两个最基本的操作,读和写。让我们先看如何读字节。 Reader interface 从数据流读取字节最基本的结构是Reader接口: type Reader interface { Read(p []byte) (n int, err error) } 该接口贯穿在整个标准库中的实现,从网络连接到文件都是内存片的包装。 读取器通过将缓冲区p传递给Read()方法,以便我们可以重用相同的字节。 如果Read()返回一个字节片而不是接受一个参数,那么读者将不得不在每个Read()调用上分配一个新的字节片。 这将对垃圾收集器造成严重破坏。 Reader接口的一个问题是它附带了一些细微的规则。 首先,当流完成时,它返回一个io.EOF错误作为使用的正常部分。 这可能会让初学者感到困惑。 其次,您的缓冲区不能保证填写。 如果您传递8字节的片段,则可以在0到8个字节之间的任何地方接收。 处理部分读取可能是凌乱和容易出错的。 幸运的是有这些问题的帮助函数。 Improving reader guarantees 假设你有一个协议你正在解析,你知道你需要从阅读器读取一个8字节的uint64值。 在这种情况下,最好使用io.ReadFull(),因为你有一个固定的大小读取: func ReadFull(r Reader, buf []byte) (n int, err error) 此功能确保您的缓冲区在返回前完全填充数据。 如果您的缓冲区部分读取,那么您将收到一个io.ErrUnexpectedEOF。 如果没有读取字节,则返回io.EOF。 这个简单的保证可以极大地简化你的代码。 要读取8个字节,您只需要这样做: buf := make([]byte, 8) if _, err := io. [Read More]
Go 

Linux 中的虚拟网络-简介

Linux 中的虚拟网络-简介 引言 随着云计算的兴起,计算机的虚拟化达到了空前的热度,计算机的虚拟化加强了服务器负载的能力,更有效的利用计算机资源。 Linux中的真实网络设备 Linux的网络设备像一个双向的管道,数据从一头进,就会从另一头出,关键要看这两头是什么?真实的网络设备中,如下图的eth0, 一头是网络协议栈,另一头网卡。用户发送数据的时候经过socket api调用,进入Linux 网络协议栈处理,再进入Linux 网络设备,最后进入网卡, 如果是接收数据则反过来。 +-------------------------------------------+ | | | +-------------------+ | | | User Application | | | +-------------------+ | | | | |.................|.........................| | ↓ | | +----------+ | | | socket | | | +----------+ | | | | |.................|.........................| | ↓ | | +------------------------+ | | | Newwork Protocol Stack | | | +------------------------+ | | | | |.................|.........................| | ↓ | | +----------------+ | | | eth0 | | | +----------------+ | | 192. [Read More]
linux 

平时整理的一些golang代码片段

golang 代码片段 by boya 老司机请忽略! 用chan实现斐波那契数列 import "fmt" func fibonacci(c, quit chan int) { x, y := 0, 1 for { select { case c <- x: x, y = y, x+y case <-quit: fmt.Println("quit") return } } } func main() { c := make(chan int) quit := make(chan int) go func() { for i := 0; i < 10; i++ { fmt.Println(<-c) } quit <- 0 }() fibonacci(c, quit) } 字符串的简单映射 [Read More]
Go 

Golang代码规范

Golang代码规范 参考https://golang.org/doc/effective_go.html 项目目录结构规范 PROJECT_NAME ├── README.md 介绍软件及文档入口 ├── bin 编译好的二进制文件,执行./build.sh自动生成,该目录也用于程序打包 ├── build.sh 自动编译的脚本 ├── doc 该项目的文档 ├── pack 打包后的程序放在此处 ├── pack.sh 自动打包的脚本,生成类似xxxx.20170713_14:45:35.tar.gz的文件,放在pack文件下 └── src 该项目的源代码 ├── main 项目主函数 ├── model 项目代码 ├── research 在实现该项目中探究的一些程序 └── vendor 存放go的库 ├── github.com/xxx 第三方库 └── xxx.com/obc 公司内部的公共库 项目的目录结构尽量做到简明、层次清楚 文件名命名规范 用小写,尽量见名思义,看见文件名就可以知道这个文件下的大概内容,对于源代码里的文件,文件名要很好的代表了一个模块实现的功能。 命名规范 包名 包名用小写,使用短命名,尽量和标准库不要冲突 接口名 单个函数的接口名以”er”作为后缀,如Reader,Writer 接口的实现则去掉“er” type Reader interface { Read(p []byte) (n int, err error) } 两个函数的接口名综合两个函数名 type WriteFlusher interface { Write([]byte) (int, error) Flush() error } 三个以上函数的接口名,类似于结构体名 [Read More]
Go 

udp编程的那些事与golang udp的实践

udp编程的那些事与golang udp的实践 tcp/ip大协议中,tcp编程大家应该比较熟,应用的场景也很多,但是udp在现实中,应用也不少,而在大部分博文中,都很少对udp的编程进行研究,最近研究了一下udp编程,正好做个记录。 sheepbao 2017.06.15 tcp Vs udp tcp和udp都是著名的传输协议,他们都是基于ip协议,都在OSI模型中传输层。tcp我们都很清楚,它提供了可靠的数据传输,而udp我们也知道,它不提供数据传输的可靠性,只是尽力传输。 他们的特性决定了它们很大的不同,tcp提供可靠性传输,有三次握手,4次分手,相当于具有逻辑上的连接,可以知道这个tcp连接的状态,所以我们都说tcp是面向连接的socket,而udp没有握手,没有分手,也不存在逻辑上的连接,所以我们也都说udp是非面向连接的socket。 我们都畏惧不知道状态的东西,所以即使tcp的协议比udp复杂很多,但对于系统应用层的编程来说,tcp编程其实比udp编程容易。而udp相对比较灵活,所以对于udp编程反而没那么容易,但其实掌握后udp编程也并不难。 udp协议 udp的首部 2 2 (byte) +---+---+---+---+---+---+---+---+ - | src port | dst port | | +---+---+---+---+---+---+---+---+ 8(bytes) | length | check sum | | +---+---+---+---+---+---+---+---+ - | | + data + | | +---+---+---+---+---+---+---+---+ udp的首部真的很简单,头2个字节表示的是原端口,后2个字节表示的是目的端口,端口是系统层区分进程的标识。接着是udp长度,最后就是校验和,这个其实很重要,现在的系统都是默认开启udp校验和的,所以我们才能确保udp消息传输的完整性。如果这个校验和关闭了,那会让我们绝对会很忧伤,因为udp不仅不能保证数据一定到达,还不能保证即使数据到了,这个数据是否是正确的。比如:我在发送端发送了“hello”,而接收端却接收到了“hell”。如果真的是这样,我们就必须自己去校验数据的正确性。还好udp默认开发了校验,我们可以保证udp的数据完整性。 udp数据的封装 +---------+ | 应用数据 | +---------+ | | v v +---------+---------+ | udp首部 | 应用数据 | +---------+---------+ | | v UDP数据报 v +---------+---------+---------+ | ip首部 | udp首部 | 应用数据 | +---------+---------+---------+ | | v IP数据报 v +---------+---------+---------+---------+---------+ |以太网首部 | ip首部 | udp首部 | 应用数据 |以太网尾部 | +---------+---------+---------+---------+---------+ | 14 20 8 4 | | -> 以太网帧 <- | 数据的封装和tcp是一样,应用层的数据加上udp首部,构成udp数据报,再加上ip首部构成ip数据报,最后加上以太网首部和尾部构成以太网帧,经过网卡发送出去。 [Read More]
Go 

Go1.9的主要更新

Go1.9的主要更新

golang每半年更新一次版本,上次最新的版本是Go1.8,而Go1.9将在今年8月释出。
Go1.9中语法的更改只有一个,那就是增加了类型别名,大部分更改是工具链,运行时,库的更改,

语法的更改

Go1.9中增加了类型别名这个语法,类型别名可以更优雅的实现当两个包之间struct的移动。类型别名的语法如下:

type T1 = T2

意思是声明一个T2类型的别名T1.

工具

并行编译

在Go1.9中并行编译啊包是默认的设置,如果需要关闭并行编译,需要设置环境变量GO19CONCURRENTCOMPILATION=0

./…可以匹配vendor了

应各位亲们的要求,之前./...不支持匹配vendor目录下的文件,现在Go1.9支持了。

性能

通常来说,很难去描述这些更改对各种场景的性能影响。大部分程序都应该运行的更快了,因为gc的提升,代码生成的更好和核心库的优化。

垃圾回收

在Go1.9之前,很多库函数都是会触发stop-the-world的,而现在只会触发并发的垃圾回收。比如:runtime.GC,debug.SetGCPerent and debug.FreeOSMemory,现在只会触发并发的垃圾回收,只会阻塞当前正在调用的goroutine,直到gc完成。
debug.SetGCPrercent函数。。。 大对象的分配性能显著的提高,当应用程序使用超大的堆(>50G),里面包含许多大对象。

runtime.ReadMemStats函数现在读取大堆的时间少于100us。

核心库

并发的map

好吧,终于官方支持了,在sync包中新增了Map类型,这个Map是线程安全的map。

time包支持显示单调

Go1.9的time包支持每个Time值都是单调时间,这样能使当系统时间改变的时候,计算两个时间差也是安全的。具体看package docsdesign doc

新的位操作包

Go1.9新增了一个包,叫math/bits,提供一些位操作的优化。

参考

go1.9 release notes

Go 

kcp-go源码解析

kcp-go源码解析 对kcp-go的源码解析,有错误之处,请一定告之。 sheepbao 2017.0612 概念 ARQ:自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层的错误纠正协议之一. RTO:Retransmission TimeOut FEC:Forward Error Correction kcp简介 kcp是一个基于udp实现快速、可靠、向前纠错的的协议,能以比TCP浪费10%-20%的带宽的代价,换取平均延迟降低30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发。查看官方文档kcp kcp-go是用go实现了kcp协议的一个库,其实kcp类似tcp,协议的实现也很多参考tcp协议的实现,滑动窗口,快速重传,选择性重传,慢启动等。 kcp和tcp一样,也分客户端和监听端。 +-+-+-+-+-+ +-+-+-+-+-+ | Client | | Server | +-+-+-+-+-+ +-+-+-+-+-+ |------ kcp data ------>| |<----- kcp data -------| kcp协议 layer model +----------------------+ | Session | +----------------------+ | KCP(ARQ) | +----------------------+ | FEC(OPTIONAL) | +----------------------+ | CRYPTO(OPTIONAL)| +----------------------+ | UDP(Packet) | +----------------------+ KCP header KCP Header Format 4 1 1 2 (Byte) +---+---+---+---+---+---+---+---+ | conv |cmd|frg| wnd | +---+---+---+---+---+---+---+---+ | ts | sn | +---+---+---+---+---+---+---+---+ | una | len | +---+---+---+---+---+---+---+---+ | | + DATA + | | +---+---+---+---+---+---+---+---+ 代码结构 src/vendor/github. [Read More]
Go 

Golang逃逸分析

Golang逃逸分析 介绍逃逸分析的概念,go怎么开启逃逸分析的log。 以下资料来自互联网,有错误之处,请一定告之。 sheepbao 2017.06.10 什么是逃逸分析 wiki上的定义 In compiler optimization, escape analysis is a method for determining the dynamic scope of pointers - where in the program a pointer can be accessed. It is related to pointer analysis and shape analysis. When a variable (or an object) is allocated in a subroutine, a pointer to the variable can escape to other threads of execution, or to calling subroutines. If an implementation uses tail call optimization (usually required for functional languages), objects may also be seen as escaping to called subroutines. [Read More]
Go 

sms golang实现的流媒体服务器

sms

用golang实现的流媒体服务器,来自开源,现在回馈给开源社区。

特性

  • 模块化,易扩展
  • 高性能,易部署,跨平台
  • 支持rtmp推拉流
  • 支持http-flv分发
  • 支持hls分发
  • 支持http接口请求来推拉流

源码编译

git clone https://github.com/zboya/sms.git  
cd sms  
./build.sh  

交叉编译

./build.sh linux arm // or ./build.sh os arch

运行

./bin/sms

项目地址

github: https://github.com/zboya/sms

Go 

golang 简介

golang 简介 来历 很久以前,有一个IT公司,这公司有个传统,允许员工拥有20%自由时间来开发实验性项目。在2007的某一天,公司的几个大牛,正在用c++开发一些比较繁琐但是核心的工作,主要包括庞大的分布式集群,大牛觉得很闹心,后来c++委员会来他们公司演讲,说c++将要添加大概35种新特性。这几个大牛的其中一个人,名为:Rob Pike,听后心中一万个xxx飘过,“c++特性还不够多吗?简化c++应该更有成就感吧”。于是乎,Rob Pike和其他几个大牛讨论了一下,怎么解决这个问题,过了一会,Rob Pike说要不我们自己搞个语言吧,名字叫“go”,非常简短,容易拼写。其他几位大牛就说好啊,然后他们找了块白板,在上面写下希望能有哪些功能(详见问尾)。接下来的时间里,大牛们开心的讨论设计这门语言的特性,经过漫长的岁月,他们决定,以c语言为原型,以及借鉴其他语言的一些特性,来解放程序员,解放自己,然后在2009年,go语言诞生。 思想 Less can be more 大道至简,小而蕴真 让事情变得复杂很容易,让事情变得简单才难 深刻的工程文化 优点 自带gc。 静态编译,编译好后,扔服务器直接运行。 简单的思想,没有继承,多态,类等。 丰富的库和详细的开发文档。 语法层支持并发,和拥有同步并发的channel类型,使并发开发变得非常方便。 简洁的语法,提高开发效率,同时提高代码的阅读性和可维护性。 超级简单的交叉编译,仅需更改环境变量。(花了我两天时间编译一个imagemagick到arm平台) 内含完善、全面的软件工程工具。Go语言自带的命令和工具相当地强大。通过它们,我们可以很轻松地完成Go语言程序的获取、编译、测试、安装、运行、运行分析等一系列工作,这几乎涉及了开发和维护一个软件的所有环节。 hello package main func main(){ println("hello, sewise") } type 主要讲讲特有的类型,其他基本类型不做介绍 slice 切片:可以理解为动态数组,类似c++的vector 声明一个slice var slice []T 如: var ints []int slice的追加 ints=append(ints,1) ints=append(ints,2,3,4,5) slice的截取 newInts1:=ints[2:3] newInts2:=ints[2:] newInts3:=ints[:4] map 字典:键值对 var json map[string]string interface 接口:方法的集合,是一种合约 栗子: 声明一个bird接口 var bird interface{ fly() } 声明一个hen对象(实现bird接口) [Read More]
Go