跳转至

编程语言

Go语言实现简易版netstat命令

netstat工作原理

netstat命令是linux系统中查看网络情况的一个命令。比如我们可以通过netstat -ntlp | grep 8080查看监听8080端口的进程。

netstat工作原理如下:

  1. 通过读取/proc/net/tcp 、/proc/net/tcp6文件,获取socket本地地址,本地端口,远程地址,远程端口,状态,inode等信息
  2. 接着扫描所有/proc/[pid]/fd目录下的的socket文件描述符,建立inode到进程pid映射
  3. 根据pid读取/proc/[pid]/cmdline文件,获取进程命令和启动参数
  4. 根据2,3步骤,即可以获得1中对应socket的相关进程信息

多网卡模式下Golang应用的流量从指定网卡流入流出方案

最近因业务需要,需要在多网卡模式下实现Go应用的流量从指定网卡流入,请求外网服务时候流量需要从该网卡流出功能。从指定网卡流入很容易实现,只要go应用listen对应网卡即可,但请求外网服务时候就相对麻烦些了。在实践中总结出有三种方案可行。各有优劣。

假定服务器网卡情况如下:

网卡 网卡IP 对应的公网IP
eth0 172.31.0.8 109.25.48.65
eth1 172.31.0.14 119.26.38.75

实际上我们的服务器使用云服务器,网卡是弹性网卡(eni),绑定的是弹性ip(eip)。三种方案对普通服务器也是能达到目的的。

Golang中信号处理

什么是信号?

信号(signal)是进程间通讯的一种方式,用来提醒进程某个事件已经发生。它属于一种异步通知进制。一个进程不必通过任何操作来等待信号的到达,事实上进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。

Golang并发调度的GMP模型

Golang的一大特色就是Goroutine。Goroutine是Golang支持高并发的重要保障。Golang可以创建成千上万个Goroutine来处理任务,将这些Goroutine分配、负载、调度到处理器上采用的是G-M-P模型。

什么是Goroutine

Goroutine = Golang + Coroutine。Goroutine是golang实现的协程,是用户级线程。Goroutine具有以下特点:

  • 相比线程,其启动的代价很小,以很小栈空间启动(2Kb左右)
  • 能够动态地伸缩栈的大小,最大可以支持到Gb级别
  • 工作在用户态,切换成很小
  • 与线程关系是n:m,即可以在n个系统线程上多工调度m个Goroutine

Golang中几种通道死锁典型案例

Golang中通道是进行数据同步一个重要手段,当主进程读取空通道,或者向没有协程读取的通道写入时候,都会发生死锁现象(编译时候提示fatal error: all goroutines are asleep - deadlock!)。下面列出几个常见死锁情况。

深入了解golang中的defer关键字

golang中的defer关键字是用来声明一个延迟函数,一般称这个函数为defer函数,该函数会在defer语句所在的函数返回之前会执行。通过defer关键字,我们可以修改函数命名返回值,进行资源释放等操作,总的来说defer函数有如下特点和功能:

  • 函数返回之前执行
  • 可以放在函数中任意位置
  • 可以同时设置多个defer函数,多个defer函数执行遵循FILO顺序
  • defer函数的传入参数在定义时就已经明确
  • 可以修改函数中的命名返回值
  • 用于文件资源,锁资源、数据库连接等释放和关闭
  • 和recover一起处理panic

本文将介绍defer上面的几个特性,如果想深入了解defer底层实现机制,可以阅读笔者写的《深入Go语言之旅 - 基础篇 - defer函数》

defer会在函数返回之前执行

当程序执行一个函数时候,会将函数的上下文(输入参数,返回值,输出参数等信息)作为栈帧放在程序内存的栈中,当函数执行完成之后,设置返回值并返回,此函数才真正完成执行。

defer语句函数会在函数返回之前执行,下面程序将会依次输出B A:

func main() {
    defer fmt.Println("A")
    fmt.Println("B")
}

PHP7各个版本新增特性

PHP从5.6 跳过6直接来到7,带来新的语言特性,更带来性能很大飞越。根据w3techs统计截止截止2019年5月18月有79%网站使用PHP做为服务端开发语言,这些网站使用的PHP版本统计如下: