Go 语言学习笔记 3:基础类型

和大多数强类型语言一样,Go 也有自己基本的类型系统。Go 语言的类型大致可以分为四大类:

  • basic types
  • aggregate types
  • reference types
  • interface types

基础类型(basic types)包括 numbers,strings,booleans。 聚合类型(aggregate types)包括 arrays , structs 。引用类型(reference types) 包括不同组,包括 pointers , slices, maps, functions, channels ,他们都是程序变量或者状态的引用。接口类型 (interface types) 是特殊的一个类型,会在后面单独介绍。

Integers

Go 数值类型包括整型,浮点数和复数。对于整型

  • 有符号 int8、int16、int32 和 int64
  • 无符号 uint8、uint16、uint32 和 uint64
  • 还有对应特定 CPU 的 int 和 uint,在不同平台上可能为 32bit 或者 64 bit。
  • rune 等同于 int32 用来表示 Unicode
  • byte 等同于 uint8 通常用来表示原始数据
  • uintptr 无符号整数类型,用来存储指针,uintptr 通常用在更加底层编程

注意 intint32 不是同一类型。

书中这边还介绍了运算符优先级和类型转换,进制转换的具体问题,详情可以参考。

Floating-Point 浮点类型

Go 提供了两种精度的浮点数 float32float64 ,常量 math.MaxFloat32 表示 float32 能表示的最大数,math.MaxFloat64 同理。

float32 类型的浮点数可以提供大约 6 个十进制数的精度,而 float64 则可以提供约 15 个十进制数的精度;通常应该优先使用 float64 类型。

Complex Numbers 复数

Go 语言提供了两种精度的复数类型:complex64 和 complex128,分别对应 float32 和 float64 两种浮点数精度。内置的 complex 函数用于构建复数,realimag 函数用来返回实部和虚部:

var x complex128 = complex(1, 2) // 1+2i
var y complex128 = complex(3, 4) // 3+4i
fmt.Println(x*y)                 // "(-5+10i)"
fmt.Println(real(x*y))           // "-5"
fmt.Println(imag(x*y))           // "10"

Booleans

布尔值只有两个值 true or false

Strings

字符串是不可变的字节序列,可以包含任何数据,通常文本会解释为 UTF8 编码 Unicode 。len 函数返回的是字节数目。

标准库中有四个包对字符串处理尤为重要:bytes、strings、strconv 和 unicode 包。strings 包提供了许多如字符串的查询、替换、比较、截断、拆分和合并等功能。

bytes 包也提供了很多类似功能的函数,但是针对和字符串有着相同结构的 []byte 类型。因为字符串是只读的,因此逐步构建字符串会导致很多分配和复制。在这种情况下,使用 bytes.Buffer 类型将会更有效,稍后我们将展示。

strconv 包提供了布尔型、整型数、浮点数和对应字符串的相互转换,还提供了双引号转义相关的转换。

unicode 包提供了 IsDigit、IsLetter、IsUpper 和 IsLower 等类似功能,它们用于给字符分类。每个函数有一个单一的 rune 类型的参数,然后返回一个布尔值。而像 ToUpper 和 ToLower 之类的转换函数将用于 rune 字符的大小写转换。所有的这些函数都是遵循 Unicode 标准定义的字母、数字等分类规范。strings 包也有类似的函数,它们是 ToUpper 和 ToLower,将原始字符串的每个字符都做相应的转换,然后返回新的字符串。

Constants

常量表达式在编译器计算,每种常量的潜在类型都是基础类型。

常量声明语句定义了常量的名字,常量值不能修改。

const pi = 3.1415

或者

const (
    e = 2.71
    pi = 3.14
)

iota 常量生成器

常量声明可以使用 iota 常量生成器初始化,用于生成一组相似规则初始化的常量,const 语句中,第一个声明常量所在行,iota 会被置为 0,然后每行加一。

type Weekday int

const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

2018-10-19 go-lang , programming

服务器监控整理

之前也有分享过两个很不错的服务器监控程序 nodequerynetdata。之后又陆陆续续发现了其他一些不错的监控程序,所以就顺手整理一下。

nodequery

这一个产品只需要在服务器上安装一个脚本,该脚本会定时将 Linux 系统状态发送到 nodequery 的网站,在他的网站后台显示,界面非常简介,提供邮件报警服务,简单的使用完全没有任何问题。

唯一的问题就是该网站已经很多年没有更新,很担心后续是否能够继续使用。

netdata

netdata 是一款开源的监控程序,安装简单,安装之后会开启一个服务端口用来展示服务器状态,这个监控页面上各个参数都有非常好看的图表来展示。

主页:https://github.com/netdata/netdata

ServerStatus

上面两种监控方案需要针对每一台服务器进行安装,如果有多台服务器需要在统一的后台进行监控,那么可以选择 ServerStatus ,ServerStatus 是一个开源的监控系统,可以在同一个页面同时检测多台服务器流量,硬盘,内存等多个参数。

主页:https://github.com/BotoX/ServerStatus 中文版:https://github.com/cppla/ServerStatus

eZ Server Monitor

一款非常轻便的服务器监控程序,PHP 脚本。同时提供了 Bash 和 Web 版本。

主页:https://www.ezservermonitor.com/ 源码:https://github.com/shevabam/ezservermonitor-web

reference


2018-10-18 server , monitor , collection

由 WebM 格式学习常见的容器和编码格式

因为使用 YouTube 所以接触到了 WebM 格式,这个格式 Google 开源的一个媒体容器格式,常见的文件后缀名是 .webm,他设计的目标是为了给 HTML5 提供视频和音频。Google 发起的 WebM 项目还有一个姊妹项目 WebP 是提供图像编码的。BSD 协议开源。1

编码格式和容器格式

我们平常所见的媒体格式,有 avi,mp3,mp4,mkv 等等,但是这些都是媒体文件容器的扩展,WikiPedia 有一份比较完整的媒体容器列表,在这份列表中我们也能看到其实 webm 格式就是 Matroska 容器的一层“皮”,mkv 格式也是 Matroska 容器的。

而这里说的容器又被称为封装格式,就是将编码好的视频,音频按照一定的规范封装到一起。当然有些容器也支持字幕,脚本之类,同一种容器中可以放不同编码的视频。

容器格式和编码格式要区别开来,放在容器中的媒体可以有不同的编码格式,编码格式指的是用特定的压缩技术对视频,音频处理。但是有些容器也能够提供二次压缩处理。常见的编码格式有:mpeg-2,mpeg-4,h.263,h.264 等等。

常见容器格式

下面简要的说一些常见的容器格式。

WebM

WebM 容器是 Matroska 一种特殊的 profile,可以封装 VP8 视频编码, Vorbis 音频编码。在 2013 年支持了 VP9 视频编码,和 Opus 音频编码。

WebM 官网 https://www.webmproject.org/

AVI

AVI 全称 Audio Video Interleaved 音频视频交错格式,微软在 1992 年推出,采用有损压缩,压缩高,因此画质相对较差,但是应用仍然非常广泛,但是随着技术发展,逐渐被淘汰了。

MOV

MOV 是 QuickTime 格式,是 Apple 公司开发的音频、视频格式,和 AVI 格式几乎同一时间出现,现在也处于被淘汰状态。

RMVB/RM

这个格式是 Real Networks 公司所指定的音频视频压缩规范,可以根据不同的网络传输速率,而指定不同的压缩比率,从而实现低速率网络上的音视频实时传送,早起的 RMVB 格式是为了在有限带宽下在线播放视频而研发,曾经一度普及整个互联网。但现在也已经被淘汰。

MKV

MKV 是 Matroska Video 的简称,MKV 最大的特点就是能够容纳多种不同类型的视频、音频、和字幕格式。

Matroska 官网 https://www.matroska.org

MPG/MPEG

MPG 又被称为 MPEG (Moving Pictures Experts Group),是国际标准化组织认可的媒体封装格式,MPEG 一般指的是容器格式,而 MPEG-1, MPEG-2 一般是指编码格式。

一般的 MPEG4 容器封装了 H.264 编码格式,AAC 音频编码格式

Ogg

Ogg 是一个自由且开放标准的容器格式,Ogg 可以放入各种自由和开放源代码的编解码器 2, Ogg 通常用于一下编码

  • Vorbis 可变比特率,16~500 kbit/s 的音频数据,有损
  • Opus 通常用于音乐,以可变比特率处理语音,6~510kbit/s
  • FLAC 无损

常见编码格式

通常情况下未编码的音频和视频内容都非常庞大,1080p 的视频一帧 1920*1080 像素大小,假设是 8 bit,一个像素 1 字节,那么一帧的大小就是 2M 大小,一般视频 1 秒为 30 帧,那么未压缩的视频几十秒钟就会达到 1Gb 大小,所以在存储时需要经过压缩。下面就是一些常见的视频压缩算法。关于更多视频编码概念的内容可以参考这里

MPEG-1

在 1992 年制定标准,针对 1.5Mbps 以下数据传输速率而设计的国际标准,也是 VCD 制作格式。用 MPEG-1 压缩算法,大致可以将 120 分钟的电影压缩到 1.2 GB 左右大小。

MPEG-2

标准定于 1994 年,设计目标为更高工业标准的图像质量和更高的传输速率,这种压缩算法主要用于 DVD 和 SVCD 制作,在高清电视和视频编辑也有广泛的应用。使用 MPEG-2 算法可以把 120 分钟的电影压缩到 4 到 8 GB 大小。

MPEG-4

标准定于 1998 年,为播放高清流媒体而设计,可以利用窄带宽,通过帧重建技术,压缩和传输数据,可以用最少的数据获得最清晰的图像质量。这种压缩算法包含了 MPEG 标准不具备的可变比特率,版权保护等功能。

这边可以额外说一下 mp3 音频压缩,指的是 MPEG-1 或者 MPEG-2 音频压缩的 Layer III3,并不是 MPEG-3。而为什么没有 MPEG-3 是因为 MPEG-2 已经足够满足 MPEG-3 提出的目标 4,所以这个 MPEG-3 标准就被废除了。

H.264

H.264 也是 MPEG-4 第十部分,因此也叫 ISO/IEC 14496-10,或者叫做 MPEG-4 AVC,MPEG-4 Part 10 。H.264 也是 MPEG-4 的一部分。

H.264 最大的优势是很高的压缩比率,在同等画质下,H.264 压缩比是 MPEG-2 的 2 倍以上,是 MPEG-4 的 1.5 到 2 倍。H.264 需要授权付费使用。

H.265

是 H.264 的升级版,在保证画质的情况下拥有更高的压缩率。也是授权使用。

常见音频编码格式

通常情况一个媒体文件必定是有视频和音频的,而上面提到的媒体容器中有些也是支持多音频编码轨的,比如说常见的电影可能包含多个国家语言音轨,而常见的 KTV 媒体格式可能需要包含一个原声轨,一个音频轨道。

AAC

AAC 是 Advanced Audio Coding,高级音频编码,出现于 1997 年,基于 MPEG-2 音频编码技术,由 Fraunhofer IIS、杜比实验室、AT&T、Sony(索尼)等公司共同开发,目的是取代 MP3 格式。2000 年,MPEG-4 标准出现后,AAC 重新集成了其特性,加入了 SBR 技术和 PS 技术,为了区别于传统的 MPEG-2 AAC 又称为 MPEG-4 AAC. 相关的规范标准分别是 ISO/IEC 13818-7,ISO/IEC 14496-3 作为一种高压缩比的音频压缩算法,AAC 压缩比通常为 18:1,也有数据说为 20:1,远胜 mp3。

在音质方面,由于采用多声道,和使用低复杂性的描述方式,使其比几乎所有的传统编码方式在同规格的情况下更胜一筹。AAC 可以支持多达 48 个音轨,15 个低频(LFE)音轨,5.1 多声道支持,更高的采样率(最高可达 96kHz,音频 CD 为 44.1kHz)和更高的采样精度(支持 8bit、16bit、24bit、32bit,音频 CD 为 16bit)以及有多种语言的兼容能力,更高的解码效率,一般来说,AAC 可以在对比 MP3 文件缩小 30% 的前提下提供更好的音质

AC-3

Digital Audio Compression Standard 杜比实验室出品,有损压缩,可以包含 6 个独立声道。最著名的是 5.1 声道, 5 代表 5 个基本声道,可以独立连接五个不同音箱,右前 RF,中 C,左前 LF,右后 RR,左后 LR,1 则代表一个低频声效,连接低音辅助音箱(20 到 120Hz),开源解码库 liba52.

APE

APE 是 Monkey’s Audio 提供的一种无损压缩格式,APE 可以无损失高音质地压缩和还原。APE 的压缩率相当高,并且音质保持得很好,获得了不少发烧用户的青睐

DTS

DTS 是 Digital Theater Systems ,数码影院系统,由 DTS 公司开发,是一种多通道音频技术,低损,环绕立体声,被广泛应用入 DVD 等高清片源上。需要授权,和杜比公司是竞争对手,常见的是 DTS 5.1,保存 5 条音频通道数据用于立体环绕声,分别是 center, left-front, right-front, left-rear, and right-rear。

FLAC

FLAC 是 Free Lossless Audio Codec,开源无损压缩编码格式,不会破坏任何原有音频,可以还原光碟音质,被很多软件硬件产品支持。

官网: http://flac.sourceforge.net/

MP3

MPEG-1 or MPEG-2 Audio Layer III 经常被称作 MP3,是目前最流行的音频编码格式,有损压缩,相关的规范标准在 ISO/IEC 11172-3, ISO/IEC 13818-3。它设计用来大幅度地降低音频数据量,将音乐以 1:10 甚至 1:12 压缩。mp3 的比特率是可变的,在高声中包含的原始信息越多,回放时品质也越高。

根据比特率,MP3 可以分为

  • MP3-CBR,固定码率
  • MP3-VBR,动态码率

Opus

Opus 是一个有损编码格式,适用于网络低延迟,实时声音传输,标准 RFC 6716。Opus 是开放格式,没有专利和限制,目标希望去熬 Speex 和 Vorbis。

总结

在归纳了目前市面上常见的媒体文件容器和编码之后,我们应该知道 WebM 是一个媒体容器,在 YouTube 上应用广泛。WebM 容器可以放入不同编码的音视频流,所以在下载了一个 webm 的文件之后可以使用

ffmpeg -i file.webm

来查看容器中的媒体文件,就我个人情况,因为 YouTube 很大一部分是用户上传,所以有些情况下 YouTube 的音频还是会选用 aac 编码,当然我也遇到过 opus。

reference

  1. https://en.wikipedia.org/wiki/WebM

  2. https://zh.wikipedia.org/wiki/Ogg

  3. https://en.wikipedia.org/wiki/MP3

  4. https://en.wikipedia.org/wiki/MPEG-3


2018-10-17 webm , youtube , google , video , ffmpeg , mp4

读万字访谈后感:软硬件公司的差别

9 月份一次出门在路上看了这篇万字采访,这篇文章主要以 Osterloh (Google 硬件部门 Leader)为脉络梳理了 Google 这几年在 硬件方面的尝试。文章中的观点并不是那么直白,但是看完却有一股气憋在心中不得不抒。作为用 Google 产品这么多年的忠实用户,Galaxy Nexus,Nexus 6 也是陪我度过了很多年,而 Google Glass 当年如何的红火,但是不得不说在 Google 在硬件确实不如其软件行业的发展,现在音箱被 Amazon Echo 压着打,手机不管是 Nexus 还是 Pixel 丝毫无法动摇 iPhone 的地位,更不用说失败的 Nexus Q,Android TV,等等。

Google 为什么做不好硬件

这篇文章其实并没有直接点明为什么 Google 做不好硬件,但是文章展示的一些细节中我们就能看出一些端倪。其中很重要的一点就是 Google 企业文化的障碍。文中这样说

发布和迭代根本不适用于硬件

Google 更擅长的是快速发布产品,在迭代中快速更新产品,然而硬件不是软件,不能直接通过云端更新就让设备焕然一新,文章中说的,调整每一个细节都有可能需要改变供应商的时间表。

在苹果,软件管理人员总是在考虑特定的产品;软件工程高级副总裁 Craig Federighi 的目标是让 iPhone 变得更棒;而 Google 优先事项总是试图同时支持自己的产品,合作伙伴和整个互联网。

上面这番话让我对软硬件区别有了更深的了解,习惯了软件思维,所以总是想着尽快地发布,但其实不论做软件产品还是做硬件产品,只有当产品足够完美再去发布。近十几年的软件行业总是越来越快,恨不得今天的电子,明天就要发布。然而事实上观察那些成功的产品,总会在发布的最初的版本就定下了未来几年甚至十几年的形态,发布之后最多也只是修修补补,反而是那些不怎么成功的产品,每隔几个月增加一些功能,每隔一年改一次版,或许有人也要反驳,正是互联网的快速迭代更新的能力,才有了让产品试错的可能,才能让产品在试错中找到发展的道路。但其实往往这样的产品,在迭代过程中丢失了初衷,在一次次尝试过程中磨损了激情和动力。

Google Glass,Nexus Q 本来可以更完美,但却在一个错误的时间,错误的场合发布,最终不了了之。

硬件和 AI 结合

有些时候确实无法去反驳这一条看似真理的话,将硬件设备和机器学习,AI 相结合,在文章中提到

在语音技术的早期阶段,用户很难找出语音助手除了设置定时器和播放音乐之外可以做什么。

智能助手 Siri 被提出之后,Amazon 有 Alex, Google 曾经有过 Google Now,Google Now on Tap,最后演变为 Google Assistant,语音助手真正成为了一个手机不可或缺的一部分。但是观察近些年这些巨头对这个“产品”的态度可以明显的看到差别,因为 Alex 并没有大规模的在手机上使用,就略过,就现在两大操作系统 Android 和 iOS 上的 Google Assistant 和 Siri 来看。Google 一心想要将 Assistant 打造的无所不能,无所不在,而 Siri 却慢慢的将控制的权利交给用户,比如在 iOS 12 中让用户自定义“捷径”。就两个产品的进化而言其实都没有错,但是无疑在 AI 并不完善的现在让 AI 不知所措甚至不如让 AI 遵循用户定义好的快捷方式来的有效。

无可置疑 Google 助手的能力要远远强于 Siri ,然而在使用的过程中非常直观的体验就是,让 Google Assistant 关掉 Wifi 都那么费劲(当然这是说的早期的时候)。或许这也是 Google 无法控制硬件带来的问题。很多人对比这些助手的时候总是哪一些,金门大桥多长多长,现在的总统是谁来提问,然而现实中大部分的问题这些助手都无法回答,而从地球到月球有多远这样的问题出现频率又有多高呢?

我想象中的手机助手至少应该能够控制手机中频繁操作的功能,比如设置提醒,设置日历,发送 SNS 消息,又比如控制 Wifi,流量开关等等。我曾记得之前看到过一些文章,介绍了产品功能在设计的时候要考虑到用户的期待。比如说用户按下一个按钮之后会发生什么,再比如说用户问完一个问题之后期待的答案。iOS 在 12 中更新的捷径,让用户自定义助手的处理,虽然门槛稍高,但却完美的避免了这一个答非所问的尴尬。

苹果公司近两年的一系列收购,Workflow,音乐识别应用 Shazam1,音乐分析引擎 Asaii 2,可以预期的是这些产品会和 Siri 甚至是 iPhone 整个产品线结合的更加紧密。这一方面弥补了软件方面的不足,另一方面也让硬件产品更加完美。

废话说了那么多,这只是对最近 Google 关停 Google+,又是审查版搜索不满的一顿发泄而已。Google 已经不是那个时候的 Google 了,倒是如今的微软,苹果更值得关心一下。

reference

  1. https://www.huxiu.com/article/264229.html

  2. https://finance.sina.com.cn/stock/usstock/c/2018-10-15/doc-ifxeuwws4317481.shtml


2018-10-16 google , apple , amazon , software , hardware , android

Jupyter 简单使用

Jupyter 是一个为了支持多语言交互式编程的项目, Jupyter Notebook 是一个开源的网络程序,允许用户创建和分享包含代码,视图,方程式,文本的文档。

  • Notebook documents 是应用产生的文档
  • Jupyter Notebook App 是一个服务端应用,可以让用户在浏览器编辑和运行 notebook documents
  • Notebook Kernel 是计算引擎,执行 Notebook document 中的代码
  • Dashboard 控制面板

Jupyter 支持超过 40 中编程语言,可以轻松通过各种格式分享笔记,代码可以生成丰富的交互输出,包括 HTML,图像,视频,LaTeX 等等。

安装 Notebook

如果有 Python 环境,比较简答,可以按照官方的文档执行

简单的安装:

pip install jupyter

或者使用官方推荐的 Anaconda 安装。

运行

执行如下代码运行

jupyter notebook

jupyter 是支持 TAB 补全的。

常用快捷键

  • Ctrl + Enter 执行单元格代码
  • Shift + Enter 执行单元格代码并且移动到下一个单元格
  • Alt + Enter 执行单元格代码,新建并移动到下一个单元格

Jupyter 能够用来做什么

Jupyter 能够

  • 数据清理,转换
  • 数值模拟
  • 建模统计
  • 数据可视化
  • 机器学习
  • 用于教育

reference


2018-10-13 jupyter , python

GraphQL 初识

在开发服务端接口的时候接触到 GraphQL 这个名词,故而有了这篇文章。因为初始,所以整理过程难免有些错误和疏漏,请留言告知。在我们面对一个新的名词,或者一门新的技术时,了解的过程可以分成这么几部分,他是什么,他解决了什么问题,他和目前同类型的技术相比优势在哪里,这样几个部分去看也就能够比较粗略,但是快速的了解一样新东西了。所以这篇文章的组织结构也以这样的方式进行。

GraphQL 是什么

GraphQL,很容易让人想起来 SQL,其实也很类似,可以理解为是一门查询语句,但和 SQL 不同的是,SQL 是查询关系型数据库,而 GraphQL 是查询 WEB 服务数据。GraphQL 是有 Facebook 开发开源,设计主要是为了解决 RESTful 接口的不足。

RESTful 在设计时,将互联网上的每一个内容都理解为资源,通过 HTTP 不同的请求方法来对资源进行增删改查,而 GraphQL 则是通过客户端自主使用查询语句来获得资源。GraphQL 并不是一门语言或者框架,而是请求数据的一种规范,协议。GraphQL 本身并不直接提供存储管理功能,也不和任何数据库绑定。

GraphQL 解决了什么问题

RESTful 接口遇到的问题

  • RESTful 接口数据格式由后端约定,调用者无法修改数据格式,只能够做适配和容错
  • 随着系统和业务变化,RESTful 接口数量爆炸式增长,不利于维护
  • 创建大而全的接口不仅影响调用速度,也浪费了移动端传输流量
  • 很多情况下客户端只需要某一个接口中特殊几个字段,但是 RESTful 会将整个数据格式返回
  • RESTful 接口在开发时需要相应的维护一套文档,而更新接口时可能导致文档修改不同步

特点

GraphQL 有如下特点:

  • 强类型,所有类型都需要预先定义
  • 服务端根据客户端提供的查询语句返回对应的 JSON

GraphQL 对外提供只有一个接口,所有请求通过该接口处理,GraphQL 内部做了路由处理。查询语句主要分为两大类,Query 查询,Mutation 修改(非幂等操作,post,put,delete 等)

比如客户端有如下查询语句

query {
  user(id: 1) {
    id
    name
  }
}

服务端返回

{
  "data": {
    "user": {
      "id": "1",
      "name": "Uncle Charlie"
    }
  }
}

服务端会返回一个和查询一致的 JSON 字串。

关于 GraphQL 的类型系统,标量类型,对象类型那就自行查看文档即可。

如果你看到这里想要亲手体验一下,那么可以访问 GitHub 提供的在线查询工具

GraphQL 和 RESTful 比较

针对上面 RESTful 出现的问题 GraphQL 的解决方案:

  • GraphQL 是强类型,需要前后端事先约定
  • GraphQL 不会随着业务发展而接口数量暴增
  • GraphQL 的调用完全由客户端控制,不会产生无用传输流量
  • GraphQL 会根据定义好的类型系统自动生成说明文档,省去了文档同步更新的麻烦

其他扩展

reference


2018-10-12 graphql , restful , api , github , facebook

Go 语言学习笔记 2:基本结构

和大部分编程语言一样,Go 也有很多内置关键字,下面这些关键字和语法相关,不能用于定义。

break case chan const continue default defer else fallthrough for func go goto if import interface map package range return select struct switch type var

三大类预定义的关键字

分类 | 关键字 ——–|———— Constants: | true false iota nil Types: | int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error Functions: | make len cap new append copy close delete complex real imag panic recover

上面这些可以用于定义。

变量定义

遵循

var name type = expression

type 可以省略

var b, f, s = true, 2.3, "four" // bool, float64, string

type 会自动推导

Short Variable Declarations

定义简短的写法

name := expression

这种写法可以省略 var 关键字。

注意 := 是变量声明,而 = 是赋值。

short variable declaration 不是总是定义左边的变量,当在同一个作用域,已经声明过的变量,那么 := 表现为赋值。

指针

variable 是包含值的一块内存区域,pointer 值是 variable 的地址,指针指向变量真正存储值的地方。不是每一个 value 都有地址,但是每一个变量都有地址。即使在不知道变量名的情况下,可以通过指针间接地读写变量相关的 value。

变量定义为 var x int, 表达式 &x 是取变量 x 的地址,会返回一个指针 *int ,读做指向 int 的指针。假设变量 b 来持有 *int:

x := 1
p := &x             // p, of type *int, points to x
fmt.Println(*p)     // "1"
*p = 2
fmt.Println(*p)     // "2"

指针的 zero value 是 nil. 如果指针指向一个变量 那么 p != nil 为 true。

var x, y int
fmt.Println(&x == &x, &x == &y, &x == nil)

使用 new 方法定义

另外一种创建 variable 的方法是使用内置方法 new, 表达式 new(T) 会创建一个类型 T 的 unnamed variable,并且将类型 T 使用 zero value 初始化,然后返回指向该值的指针,也就是 *T

p := new(int)
fmt.Println(*p)         // "0"
*p = 2
fmt.Println(*p)         // "2"

使用 new 方法创建,除了没有变量名字和普通创建没有什么差别。所以下面两个方法等同

func newInt() *int {
    return new(int)
}

func newInt() *int {
    var dummy int
    return &dummy
}

变量的生命周期

  • 包变量一直常驻在内存到程序的结束,然后被系统垃圾回收器回收。
  • 局部变量,一直生存,直到没有外部指针,或者函数退出,没有路劲可以访问到该变量

赋值

赋值其实没啥好说的,任何语言都不可或缺。

但是 Go 支持 元组赋值 Tuple Assignment,那么就可以和 Python 一样,允许多个值一起被赋值

x, y = y, x

类型定义

类型定义

type name underlying-type

type Celsius float64

包和文件

Go 语言中的包 (package) 和其他语言中的 库(libraries),或者模块(module)作用是一样的,为了支持模块化,封装和重用。

Go 中的包让我们控制内部名字是否暴露给外部。就和之前说的那样,大写字母开头的会暴露给外部。

当一个 go 文件包名为 main, 那么就是告诉 go 编译程序,这是一个可执行程序,go 编译器就会尝试将它编译为一个二进制文件。

导入包

导入包需要用到 import 关键字。

import "fmt"
import "net/http"

Go 编译器会去 Go 的环境变量 GOROOTGOPATH 中寻找导入的内容。关于这两个环境变量可以参考上一篇文章。

Go 也支持远程导入包,比如导入 github 上的包

import "github.com/xxx/xxx"

go get 工具可以递归获取依赖。

重命名导入的包

import (
    "fmt"
    myfmt "mylib/fmt"
)

初始化包

每个包都可以包含多个 init 函数,每个 init 函数都会在 main 函数之前执行,init 函数通常用来做初始化变量,设置包等初始化工作。

Scope

作用域,不要和生命周期搞混,变量声明的作用域是编译期的概念,而变量的生命周期是运行时概念。

一个句法上的块 (block)指的是花括号包围的一组语句。

func f() {}

var g = "g"

func main() {
    f := "f"
    fmt.Println(f) // "f"; local var f shadows package-level func f
    fmt.Println(g) // "g"; package-level var
    fmt.Println(h) // compile error: undefined: h
}

reference

  • 《The Go Programming Language 2015》

2018-10-10 go-lang , google , programming

go 语言学习笔记 1:基本介绍和使用

并发

Go 语言在语言级别支持协程,叫 goroutine。Go 语言标准库提供的所有系统调用 (syscall) 操作,当然也包括所有同步 IO 操作,都会出让 CPU 给其他 goroutine

Go 语言推荐采用“Erlang 风格的并发模型”的编程范式来实现进程间通信。

编码风格

要求 public 变量以大写字母开头,private 变量以小写字母开头。

花括号写法,还有错误处理,都有详细的规定。Go 语言也是至今为止学习的语言中,唯一一个将编码风格写入语言要求的。

变量

对于 Go 的变量,推荐使用 驼峰式

包名

包名要求小写。

编程哲学

Go 语言反对重载,反对继承,反对虚函数和虚函数重载,Go 提供了继承但是使用组合文法提供。

Go 语言是静态类型语言。

语言特性

一些值得提前了解的语言特性

  • 垃圾回收
  • 内置 map 类型,支持数组切片
  • 函数多返回值,这一点和动态语言的 Python 有些相像
  • 错误处理,Go 语言引入了 defer,panic 和 recover 三个关键字来处理错误。
  • 匿名函数和闭包,函数也是值类型,可以传递
  • 类型和接口,Go 语言的类型定义非常接近 C 语言中的结构 struct,但是 Go 语言没有沿袭 C++ 和 Java 传统构造一个复杂类型系统,不支持继承和重载,只支持基本的类型组合。

并发编程

Go 语言引入 goroutine 概念,关键字 go, 可以让函数以 goroutine 协程方式执行。Go 语言使用 channel 来实现通信顺序进程(CSP,Communicating Sequential Process)模型,方便跨 goroutine 通信。

安装使用

这里 下载,然后解压并添加环境变量

tar -C /usr/local -xzf go1.11.1.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

然后设置 GOPATH 环境变量

安装 C 相关工具

sudo apt-get install bison ed gawk gcc libc6-dev make

安装目录

在安装好的 Go 目录下,有几个重要的目录

  • /bin,可执行文件,编译器,Go 工具
  • /doc
  • /lib,文档模板
  • /misc,支持 Go 编辑器相关配置
  • /os_arch 包含标准库包对象文件 .a
  • /src,源代码
  • /src/cmd,Go 和 C 编译器和命令行脚本

几个重要的环境变量

  • $GOROOT 表示该 org 在你的电脑上的安装位置,它的值一般都是 $HOME/GOROOT , 当然,你也可以安装在别的地方
  • $GOARCH 表示目标机器的处理器架构,它的值可以是 386、amd64 或 arm
  • $GOOS 表示目标机器的操作系统,它的值可以是 arwin、freebsd、linux 或 windows
  • $GOPATH 认采用和 $GOROOT 一样的值,但从 Go1.11 本开始,你必须修改为其它路径。它可以包含多个包含 Go 语言源码文件、包文件和可执行文件的路径,而这些路径下又必须分别包含三个规定的目录:src 、pkg 和 bin , 这三个目录分别用于存放源码文件、包文件和可执行文件

Hello World

创建一个 workspace,然后开始 hello world,在 workspace 下新建 src/hello 目录,在目录下创建文件 vim hello.go

package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n")
}

退出文件,在 hello 目录下执行 go build,此时会生成一二可执行文件 hello,执行 ./hello 可以看到输出。

  • 每个 Go 源代码文件的开头都是一个 package 声明,表示该 Go 代码所属的包
  • 在包声明之后,是一系列的 import 语句,用于导入该程序所依赖的包,不得包含在源代码文件中没有用到的包,否则 Go 编译器会报编译错误
  • Go 语言的 main() 函数不能带参数,也不能定义返回值。命令行传入的参数在 os.Args 变量中保存。

函数体定义

func 函数名(参数列表)(返回值列表) {
    // 函数体
}

如果不进行编译,也可以直接 go run hello.go 来运行。

类型系统

在 Go 语言中有四个关键字和定义类型相关,var,const,typefunc 前两个和变量相关,第三个可以用来自定义类型,func 定义方法。

内置类型

和其他强类型语言一样,Go 语言内置一些基础类型,比如 Strings,Numbers(int32,int64,float32,float64 等等),Booleans。这些类型本质上是原始类型。当对值进行增加或者删除市,会创建一个新值。当把这些值传递给方法时,会传递一个对应值的副本。

引用类型

Go 语言中有下面几个引用类型:切片、映射、通道、接口和函数类型。当声明上述类型时,创建的变量被称为标头(header)值,每个引用类型创建的标头值是包含一个指向底层数据结构的指针。

header 中包含一个指针,通过复制来传递一个引用类型的值的副本。

结构类型

结构类型用来描述一组数据值。

我们对于一些事物的不理解或者畏惧,原因都在于这些事情所有意无意带有的绚丽外衣和神秘面纱。只要揭开这一层直达本质,就会发现一切其实都很简单。

reference


2018-10-09 go-lang , google , java , programming

跨平台开源卡片记忆工具 anki

一开始的时候我无法用一句话来形容这个软件,大部分人将他称为背单词软件,部分人有拿他作为知识笔记软件,甚至有人拿他来学习乐谱,诗歌,但总之如果要用简单的话来描述这个软件,那么跨平台必定是关键词,另外一个关键词就是卡片,在另外一个就是循环记忆,那么至于卡片上承载什么样的内容,就完全由用户来决定了。

下载

几个概念

Deck

来自朗文的解释:a set of playing cards,翻译为一组卡牌

Profile

朗文的解释:a short description that gives important details about a person, a group of people, or a place,翻译为档案,介绍也都可以,在 Anki 的 File 菜单中,可以切换 Profile,不至于导入别人的卡牌之后弄乱自己的设置,或者自己在使用时也可以根据不同的场景定义不同的 Profile

学习资源

官网那一定是最全的,包含各国语言

插件

Add-ons

推荐几个(只适用于我目前使用的 2.1 版本,随着时间变化,下面的 id 可能失效):

  • 900455869 TTS 发音
  • 1612375712 触发全屏
  • 2055492159 AnkiConnect

自动化制作卡片

Chrome to Anki

需要借助一款 Chrome 插件

和一个 Anki 插件

这两个插件都是开源 12 的,看官方的说明也很简单就略过了。

GoldenDict to Anki

虽然目前一直在寻找方法能够间 GoldenDict 查词记录自动制作卡片到 Anki,但是目前尚未找到合适的方法,虽然有了解到可以使用 mdx-sever 共享一个 HTTP 服务,然后使用上面的方法自动制作,但感觉依然有些麻烦。

Kindle to Anki

对于 Kindle 我很少将它连到电脑上做导出导入的事情,所以这个不准备弄了。

  1. https://github.com/ninja33/anki-dict-helper

  2. https://github.com/FooSoft/anki-connect


2018-10-05 anki , learning , notes

每天学习一个命令:用 ab 命令来进行 HTTP 服务压测

ab 是针对 HTTP 服务进行性能压力测试的工具,它最初被设计用来测量 Apache 服务器的性能指标,主要用来测试 Apache 服务器每秒能够处理多少请求以及响应时间,但这个命令也可以用来测试通用的 HTTP 服务器性能,比如 Nginx,tomcat,resin 等等。

几个概念

吞吐量 Requests per second

吞吐量是系统每秒钟处理的请求数量,可以通过 总请求数量 / 请求花费时间 来计算。

服务器平均请求等待时间

服务器平均请求等待时间指的是服务器平均处理一个请求花费的时间,公式是 总花费时间 / 请求数量,这个指标是吞吐量的倒数。(Time per request)

并发连接数

指的是某一时刻服务器同时接受的连接数。

安装使用

安装

sudo apt install apache2-utils

使用

ab -c 10 -n 10000 -k -H "Accept-Encoding: gzip, deflate" http://localhost:8080/

解释

  • -c concurrency 并发数
  • -n requests 一次测试的请求数量
  • -k 表示 keep alive,保持连接
  • -H headers 自定义 Header

举例

ab -k -c 10 -n 100 https://www.einverne.info/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.einverne.info (be patient).....done


Server Software:        nginx
Server Hostname:        www.einverne.info
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128

Document Path:          /
Document Length:        53802 bytes

Concurrency Level:      10
Time taken for tests:   1.125 seconds
Complete requests:      100
Failed requests:        0
Keep-Alive requests:    0
Total transferred:      5400681 bytes
HTML transferred:       5380200 bytes
Requests per second:    88.91 [#/sec] (mean)
Time per request:       112.470 [ms] (mean)
Time per request:       11.247 [ms] (mean, across all concurrent requests)
Transfer rate:          4689.35 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        5   48  35.3     44     163
Processing:     9   62  65.7     47     559
Waiting:        7   59  64.7     45     543
Total:         25  109  75.4     83     564

Percentage of the requests served within a certain time (ms)
  50%     83
  66%    111
  75%    123
  80%    128
  90%    225
  95%    275
  98%    337
  99%    564
 100%    564 (longest request)

实际使用

登录问题

对于实际场景中经常需要用的登录问题,如果接口需要验证 Cookie ,那么使用 -C 写到 Cookie 内容

ab -n 100 -C key=value http://localhost

或者使用 -HCookie 自定义多个字段

ab -n 100 -H "Cookie: Key1=Value1; Key2=Value2" http://localhost

总结

ab 只能测试简单的 RESTful 接口,只能应付简单的压测任务。如果需要更加专业的压测工具可以使用 jmeter。

reference


2018-10-03 linux , ab , apache , command

电子书

Google+

最近文章

  • Go 语言学习笔记 3:基础类型 和大多数强类型语言一样,Go 也有自己基本的类型系统。Go 语言的类型大致可以分为四大类:
  • 服务器监控整理 之前也有分享过两个很不错的服务器监控程序 nodequery 和 netdata。之后又陆陆续续发现了其他一些不错的监控程序,所以就顺手整理一下。
  • 由 WebM 格式学习常见的容器和编码格式 因为使用 YouTube 所以接触到了 WebM 格式,这个格式 Google 开源的一个媒体容器格式,常见的文件后缀名是 .webm,他设计的目标是为了给 HTML5 提供视频和音频。Google 发起的 WebM 项目还有一个姊妹项目 WebP 是提供图像编码的。BSD 协议开源。1 https://en.wikipedia.org/wiki/WebM ↩
  • 读万字访谈后感:软硬件公司的差别 9 月份一次出门在路上看了这篇万字采访,这篇文章主要以 Osterloh (Google 硬件部门 Leader)为脉络梳理了 Google 这几年在 硬件方面的尝试。文章中的观点并不是那么直白,但是看完却有一股气憋在心中不得不抒。作为用 Google 产品这么多年的忠实用户,Galaxy Nexus,Nexus 6 也是陪我度过了很多年,而 Google Glass 当年如何的红火,但是不得不说在 Google 在硬件确实不如其软件行业的发展,现在音箱被 Amazon Echo 压着打,手机不管是 Nexus 还是 Pixel 丝毫无法动摇 iPhone 的地位,更不用说失败的 Nexus Q,Android TV,等等。
  • Jupyter 简单使用 Jupyter 是一个为了支持多语言交互式编程的项目, Jupyter Notebook 是一个开源的网络程序,允许用户创建和分享包含代码,视图,方程式,文本的文档。