Golang实现微型数学运算解释器

Julyqi 发表了文章 • 5 个评论 • 323 次浏览 • 2017-08-02 15:02 • 来自相关话题

对于一般的解释器来说,通常需要三个步骤:

词法分析 语法分析 指令执行

这篇文章所介绍的小型数学解释器则没有这么复杂的过程,原因在于语法设计及其简单。我们来看一下最终的使用效果, 源码在这儿:查看全部

对于一般的解释器来说,通常需要三个步骤:


词法分析
语法分析
指令执行


这篇文章所介绍的小型数学解释器则没有这么复杂的过程,原因在于语法设计及其简单。我们来看一下最终的使用效果, 源码在这儿:http://t.cn/R9JzbgY


大家也可以自己试试,遇到什么可以交流一下。

Golang bytes 包源码解析

qiangmzsx 回复了问题 • 2 人关注 • 1 个回复 • 406 次浏览 • 2017-08-01 20:48 • 来自相关话题

Golang优秀开源项目汇总(持续更新。。。)

Julyqi 发表了文章 • 1 个评论 • 640 次浏览 • 2017-07-31 14:52 • 来自相关话题

分享一些优秀的开源项目,能给我们开发者带来一些灵感,哪里不对的地方可以指出来哦。

项目列表如下 http://t.cn/R9cTHZu

也希望大家多多补充一些...

分享一些优秀的开源项目,能给我们开发者带来一些灵感,哪里不对的地方可以指出来哦。


项目列表如下 http://t.cn/R9cTHZu


也希望大家多多补充一些 哈

理解Golang并发编程

dasheng 发表了文章 • 2 个评论 • 1403 次浏览 • 2017-07-29 12:58 • 来自相关话题

点击查看原文章

concurrency vs parallelism

并发和并行是彼此相关的两个... 查看全部

点击查看原文章


concurrency vs parallelism


并发和并行是彼此相关的两个概念,并不能完全等价。在程序中,并发强调的是独立执行的程序的组合;并行强调的是同时执行计算任务[1]。

计算机核心的数量决定了并行计算的能力,大多数人类作为“单核”动物(老顽童小龙女除外),可以说自己在并发某些任务,如我在听歌写代码,但是不能说这两件事在并行,参考下图:
![concurrency vs parallelism](/images/currency vs parallelism.png)
Golang的并发模型源于Communicating Sequential Processes (CSP),通过提供goroutine和channel来实现并发编程模式。


Goroutine


Goroutine由Go运行时创建和管理,是用于调度CPU资源的“最小单元”,和OS的线程相比更轻量[2]:



  • 内存消耗更低只需2kB初始栈空间,而线程初始要1Mb的空间;

  • 由golang的运行时环境创建和销毁,更加廉价,不支持手动管理;

  • 切换效率更高等。
    Goroutine和线程的关系如下图所示:
    ![goroutine vs thread](/images/goroutine vs thread.png)


我们可以轻松地创建成百上千的goroutine,而不会降低程序的执行效率。

通过goroutine可以让一个函数和其他的函数并行执行。可以在函数调用前面加上go关键字,方便地创建一个goroutine。

main函数本身也是一个goroutine[3]。

举例如下:


package main

import "fmt"

func main() {
fmt.Println("begin main goroutine")
go hello()
fmt.Println("end main goroutine")
}

func hello() {
fmt.Println("begin hello goroutine")
}

输出:


begin main goroutine
end main goroutine

上面的例子中,并不会输出begin hello goroutine,这是因为,通过使用goroutine,我们不需要等待函数调用的返回结果,而会接着执行下面的代码。

可以在go hello()后面添加:


time.Sleep(1 * time.Second)

就可以正常输出begin hello goroutine


channel


Go提供了一种机制能够使goroutine之间进行通信和同步,它就是channel。

channel是一种类型,关键字chan和channel传输内容的类型共同定义了某一channel。

定义方式为:var c chan string = make(chan string),也可以简写为:var c = make(chan string)c := make(chan string)


通过左箭头<-操作符操作channel变量:



  • c <- "ping"向channel发送一个值为“ping”的字符串,

  • msg := <- c接收channel中的一个值,并赋給msg。


package main

import (
"fmt"
"strconv"
"time"
)

func main() {
c := make(chan string)
go ping(c)
go print(c)
var input string
fmt.Scanln(&input)
}

func ping(c chan string) {
for i := 0; ; i++ {
c <- strconv.Itoa(i)
}
}

func print(c chan string) {
for {
<-c
fmt.Println("reveving: " + <-c)
time.Sleep(1 * time.Second)
}
}

输出:


reveving: 1
reveving: 3
reveving: 5
reveving: 7
reveving: 9
...

按功能,可以将channel分为只发送或只接收channel,通过修改函数签名的channel形参类型来指定channel的“方向”:



  • 只允许发送: func ping(c chan<- string)

  • 只允许接收: func print(c <-chan string)

  • 任何对只发送channel的接收操作和只接收channel的发送操作都会产生编译错误。

  • 不指定方向的channel被称作“双向”channel,可以将“双向”channel最为参数,传递给接收单向channel的函数,反之,则不行。


unbuffered channel


非缓冲channel,也就是缓冲池大小为0的channel或者同步channel,上面的例子都是非缓冲channel,定义方式为:



  • ch := make(chan int)

  • ch := make(chan int, 0)


非缓冲channel在同步读时,如果channel的sendq中有就绪的goroutine,那么就取出(copy)数据并释放发送方goroutine;如果没有就绪的goroutine,那么将接收方goroutine挂起。

非缓冲channel在同步写时,如果channel的recvq中有就绪的goroutine,那么就取出(copy)数据到接收方goroutine,并使其就绪;如果没有,那么将发送发goroutine挂起。


buffered channel


缓冲channel只能容纳固定量的数据,当缓冲池满之后,发送发被阻塞,直到数据被接收释放缓冲池,定义如下:



  • ch := make(chan int)
    缓冲channel可以用来限制吞吐量,例子如下:


package main

import (
"fmt"
"time"
)

// Request struct
type Request struct {
}

var sem = make(chan int, 5) // Create a buffered channel witch capacity of 5

func main() {
queue := make(chan *Request)
go start(queue)
go serve(queue)
var input string
fmt.Scanln(&input)
}

func start(queue chan *Request) {
for {
queue <- &Request{}
}
}

func serve(queue chan *Request) {
for req := range queue {
sem <- 1 // Put on signal to channel
go handle(req) // Don't wait for handle to finish.
}
}

func handle(r *Request) {
process(r) // May take a long time.
<-sem // Done; enable next request to run.
}

func process(r *Request) {
fmt.Println("process")
time.Sleep(4 * time.Second)
}

每隔4秒钟,输出:


process
process
process
process
process

select


针对于channel,Golang提供了一个类似switch的功能,即select,使用如下:



  1. select选择第一个就绪的channel进行处理

  2. 如果有多个就绪的channel,则随机选择一个channel进行处理

  3. 如果没有就绪的channel,则等待直到某一channel就绪

  4. 如果有default,则在3情形中不会等待,而是立即执行default中的代码


package main

import (
"fmt"
"time"
)

func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go ping(ch1)
go pong(ch2)
go print(ch1, ch2)
var input string
fmt.Scanln(&input)
}

func ping(ch chan int) {
time.Sleep(2 * time.Second)
ch<-1
}

func pong(ch chan int) {
time.Sleep(3 * time.Second)
ch<-2
}

func print(ch1, ch2 chan int) {
select {
case msg := <-ch1:
fmt.Println(msg)
case msg := <-ch2:
fmt.Println(msg)
}
}

两秒钟之后,输出:1

在select语句中添加下面代码:


default:
fmt.Println("nothing received.")

输出: nothing received.


总结


Golang将线程抽象出来成为轻量级的goroutine,开发者不再需要过多地关注OS层面的逻辑,终于能够从并发编程中解放出来。

channel作为goroutine通信的媒介,安全高效的实现了goroutine之间的通信和共享内存。

用Effetive go中的一句话来总结[4]:



Do not communicate by sharing memory; instead, share memory by communicating.



Reference


[1] https://blog.golang.org/concurrency-is-not-parallelism

[2] http://blog.nindalf.com/how-goroutines-work/

[3] https://www.golang-book.com/books/intro/10

[4] https://golang.org/doc/effective_go.html

NoPoint Docker — 云时代的程序分发方式

Julyqi 发表了文章 • 0 个评论 • 281 次浏览 • 2017-07-28 16:17 • 来自相关话题

要说最近一年云计算业界有什么大事件?Google Compute Engine 的正式发布?Azure入华?还是AWS落地中国?留在每个人大脑中的印象可能各不相同,但要是让笔者来排名的话那么Docker绝对应该算是第一位的。如果你之前听说过它的话,那么也... 查看全部

要说最近一年云计算业界有什么大事件?Google Compute Engine 的正式发布?Azure入华?还是AWS落地中国?留在每个人大脑中的印象可能各不相同,但要是让笔者来排名的话那么Docker绝对应该算是第一位的。如果你之前听说过它的话,那么也许你会说“没错,就是它”,因为几乎世界各地的开发、运维都在谈论着Docker;如果你还没听说过Docker,那么我真的建议你花上5分钟来阅读本文。


https://community.clouderwork.com/article/view/59633469d009d.html


总之笔者认为Docker还是非常有趣的一个东西,值得大家花些时间体验一下,相信在各位的工作中多多少少都能用的上Docker。

记一次golang的gzip优化

thinkboy 发表了文章 • 4 个评论 • 796 次浏览 • 2017-07-26 21:11 • 来自相关话题

背景

近期使用Golang官方的"compress/gzip"包对数据压缩返回给App,此场景特性:数据不固定、高并发。在实际过程中发现一个简单逻辑的API服务,几百QPS的情况下CPU却很高达到几个核负载。查看全部
					

背景


近期使用Golang官方的"compress/gzip"包对数据压缩返回给App,此场景特性:数据不固定、高并发。在实际过程中发现一个简单逻辑的API服务,几百QPS的情况下CPU却很高达到几个核负载。

问题追踪


通过golang自带工具pprof抓图分析CPU,如下图(由于有业务代码,所以部分信息遮盖了):
http://img-hxy021.didistatic.com/static/way/do1_In6jEmpzPXAca5KnRNUD


通过此图可以看出,整个工程里有两个CPU消耗大头:1)GC高 2)大部分CPU耗在Gzip上.看方法属于New操作,再加上GC高,很容易往一个方向上去想,就是对象创建过多造成。


于是google搜了一些资料发现有人尝试优化gzip,地址:https://github.com/klauspost/compress/tree/master/gzip,但经过测试虽然速度提升20~30%,但是并不兼容原生Gzip,似乎并不是一个很通用的方案


分析源码


1.首先看下demo里原生的使用方式


demo地址:https://github.com/thinkboy/gzip-benchmark


func OldGzip(wr http.ResponseWriter, r *http.Request) {
buf := new(bytes.Buffer)
w := gzip.NewWriter(buf)

leng, err := w.Write(originBuff)
if err != nil || leng == 0 {
return
}
err = w.Flush()
if err != nil {
return
}
err = w.Close()
if err != nil {
return
}
b := buf.Bytes()
wr.Write(b)

// 查看是否兼容go官方gzip
/*gr, _ := gzip.NewReader(buf)
defer gr.Close()
rBuf, err := ioutil.ReadAll(gr)
if err != nil {
panic(err)
}
fmt.Println(string(rBuf))*/
}

2.其次看下官方gzip的实现,如下图:
http://img-hxy021.didistatic.com/static/way/do1_TIZjHEQ3BarilNCNC3Z8
http://img-hxy021.didistatic.com/static/way/do1_QvSBEc6YCpXRafIxvK9C


跟踪代码寻找几处与Pprof图相关的有New操作的地方,首先第一张图每次都会New一个Writer,然后在第二张图里的Write的时候,每次又都会为新创建的Writer分配一个压缩器。对于对象的反复创建有一个通用的思路,使用对象池。


3.尝试使用对象池


http://img-hxy021.didistatic.com/static/way/do1_HQTmIbkd8zBFJVKPmPwr


通过上图我们发现gzip的Writer有个Reset()方法,该方法调用的init()里的实现是如果已经存在压缩器,就复用并且Reset()。也就是说其实官方已经提供了一种方式让用户不再反复New Writer。然后我们可以这样改造下实现代码:


func MyGzip(wr http.ResponseWriter, r *http.Request) {
buf := spBuffer.Get().(*bytes.Buffer)
w := spWriter.Get().(*gzip.Writer)
w.Reset(buf)
defer func() {
// 归还buff
buf.Reset()
spBuffer.Put(buf)
// 归还Writer
spWriter.Put(w)
}()

leng, err := w.Write(originBuff)
if err != nil || leng == 0 {
return
}
err = w.Flush()
if err != nil {
return
}
err = w.Close()
if err != nil {
return
}
b := buf.Bytes()
wr.Write(b)

// 查看是否兼容go官方gzip
/*gr, _ := gzip.NewReader(buf)
defer gr.Close()
rBuf, err := ioutil.ReadAll(gr)
if err != nil {
panic(err)
}
fmt.Println(string(rBuf))*/
}

我们给压缩过程中用到的Buffer以及Writer定义对象池spBuffer、spWriter,然后每次api请求都从对象池里去取,然后Reset,从而绕过New操作。


这里容易产生一个疑问:对象池其实本身就是一个“全局大锁”,高并发场景下这把全局大锁影响有多大?(其实有一种深度优化的方式就是拆锁,比如依据某个ID进行取余取不同的对象池。这里就拿一把大锁来实验).


下面看一下此次改造后的压测结果(QPS: 3000):


不使用对象池(CPU 使用28个核左右):


http://img-hxy021.didistatic.com/static/way/do1_gmYIJXtQ7KNJtts9itST


使用对象池(CPU 使用22个核左右):


http://img-hxy021.didistatic.com/static/way/do1_mJGJQGHiQNYvumIZiqTx


通过CPU使用来看有消耗降低22%左右,由于QPS并不是很高,所以这里对象池的“全局大锁”的影响暂且可以忽略。


结论


针对官方Gzip的压缩可以使用对象池来改善。


klauspost所提供的方案也列举在demo中了,虽然属于自己改了压缩算法不兼容Golang官方包,但亲测对压缩速度也提升了很大百分比。使用该库+对象池的方式可能会达到更显著优化效果。


demo地址:https://github.com/thinkboy/gzip-benchmark

GOLANG中DEFER, PANIC, RECOVER用法

回复

haohongfan 发起了问题 • 1 人关注 • 0 个回复 • 440 次浏览 • 2017-07-21 11:37 • 来自相关话题

Go面试题答案与解析

ysqi 发表了文章 • 13 个评论 • 1099 次浏览 • 2017-07-20 12:59 • 来自相关话题

pprof简单教程

caibirdme 发表了文章 • 4 个评论 • 793 次浏览 • 2017-07-20 11:24 • 来自相关话题

昨晚写了个pprof的简单教程放在了github上,结合一个比较脑残例子通过pprof找到瓶颈并进行优化,翔见 查看全部

昨晚写了个pprof的简单教程放在了github上,结合一个比较脑残例子通过pprof找到瓶颈并进行优化,翔见 hand-to-hand-optimize-go

glide从入门到使用教程

qiangmzsx 发表了文章 • 3 个评论 • 846 次浏览 • 2017-07-19 18:58 • 来自相关话题

介绍

不论是开发Java还是你正在学习的Golang,都会遇到依赖管理问题。Java有牛逼轰轰的Maven和Gradle。 Golang亦有godep、govendor、glide、gvt、gopack... 查看全部

介绍


不论是开发Java还是你正在学习的Golang,都会遇到依赖管理问题。Java有牛逼轰轰的Maven和Gradle。
Golang亦有godep、govendor、glide、gvt、gopack等等,本文主要给大家介绍gilde
glide是Golang的包管理工具,是为了解决Golang依赖问题的。
为什么需要glide?
原因很简单,Go 语言原生包管理的缺陷。罗列一下golang的 get 子命令管理依赖有很多大缺陷:



  • 能拉取源码的平台很有限,绝大多数依赖的是 github.com

  • 不能区分版本,以至于令开发者以最后一项包名作为版本划分

  • 依赖 列表/关系 无法持久化到本地,需要找出所有依赖包然后一个个 go get

  • 只能依赖本地全局仓库(GOPATH/GOROOT),无法将库放置于局部仓库($PROJECT_HOME/vendor)


安装


Golang环境设置


采用vendor目录特性,Go 1.5 做为试验特性加入(需要指定 GO15VENDOREXPERIMENT=1 环境变量),并在 Go 1.6 正式引入的一个概念。多数 go 依赖解决方案都基于它的。GO15VENDOREXPERIMENT 是 Go 1.5 版本新增的一个环境变量,如果将值改为 1 则表示启用。它可以将项目根目录名为 vendor 的目录添加到 Go 的库搜寻路径中,实现一个局部依赖的效果。

特性在 1.5 版本作为实验特性被添加,1.6 中默认被启用,1.7 移除变量加入标准中。

Go 提供了原始的 go get ,让第三方包管理可以基于 go get 做扩展。GO15VENDOREXPERIMENT 特性让局部依赖成为现实。Go 官方在给第三方包管理营造条件以及引导开发者用户至所推荐的方向,促进社区的繁荣。证明了一个语言技术的生态不仅仅只能靠官方或者取决于官方的完善程度。


//设置环境变量 使用vendor目录
GO15VENDOREXPERIMENT=1

为什么要选择glide?
Glide 是众多实现 GO15VENDOREXPERIMENT 特性的包管理工具之一,但它是本文最为推荐的,具体为什么推荐它,原因很简单,因为它目前最受关注。
几大主要功能:



  • 持久化依赖列表至配置文件中,包括依赖版本(支持范围限定)以及私人仓库等

  • 持久化关系树至 lock 文件中(类似于 yarn 和 cargo),以重复拉取相同版本依赖

  • 兼容 go get 所支持的版本控制系统:Git, Bzr, HG, and SVN

  • 支持 GO15VENDOREXPERIMENT 特性,使得不同项目可以依赖相同项目的不同版本

  • 可以导入其他工具配置,例如: Godep, GPM, Gom, and GB


安装glide


$ go get github.com/Masterminds/glide
$ go install github.com/Masterminds/glide

验证


$ glide
NAME:
glide - Vendor Package Management for your Go projects.

Each project should have a 'glide.yaml' file in the project directory. Files
look something like this:

package: github.com/Masterminds/glide
imports:
- package: github.com/Masterminds/cookoo
version: 1.1.0
- package: github.com/kylelemons/go-gypsy
subpackages:
- yaml

For more details on the 'glide.yaml' files see the documentation at
https://glide.sh/docs/glide.yaml

USAGE:
glide [global options] command [command options] [arguments...]

VERSION:
0.13.0-dev

COMMANDS:
create, init Initialize a new project, creating a glide.yaml file
config-wizard, cw Wizard that makes optional suggestions to improve config in a glide.yaml file.
get Install one or more packages into `vendor/` and add dependency to glide.yaml.
remove, rm Remove a package from the glide.yaml file, and regenerate the lock file.
import Import files from other dependency management systems.
name Print the name of this project.
novendor, nv List all non-vendor paths in a directory.
rebuild Rebuild ('go build') the dependencies
install, i Install a project's dependencies
update, up Update a project's dependencies
tree (Deprecated) Tree prints the dependencies of this project as a tree.
list List prints all dependencies that the present code references.
info Info prints information about this project
cache-clear, cc Clears the Glide cache.
about Learn about Glide
mirror Manage mirrors
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--yaml value, -y value Set a YAML configuration file. (default: "glide.yaml")
--quiet, -q Quiet (no info or debug messages)
--debug Print debug verbose informational messages
--home value The location of Glide files (default: "/home/users/qiangmzsx/.glide") [$GLIDE_HOME]
--tmp value The temp directory to use. Defaults to systems temp [$GLIDE_TMP]
--no-color Turn off colored output for log messages
--help, -h show help
--version, -v print the version

看到这样,那就恭喜你,已经安装成功了!!!


使用


篇幅有限,我只介绍经常使用到的。
先进入在GOPATH的一个项目中。


cd $GOPATH/src/foor

初始化 (glide init)


$ glide init
[INFO] Generating a YAML configuration file and guessing the dependencies
[INFO] Attempting to import from other package managers (use --skip-import to skip)
[INFO] Scanning code to look for dependencies
[INFO] --> Found reference to github.com/urfave/cli
[INFO] Writing configuration file (glide.yaml)
[INFO] Would you like Glide to help you find ways to improve your glide.yaml configuration?
[INFO] If you want to revisit this step you can use the config-wizard command at any time.
[INFO] Yes (Y) or No (N)?
Y
[INFO] Loading mirrors from mirrors.yaml file
[INFO] Looking for dependencies to make suggestions on
[INFO] --> Scanning for dependencies not using version ranges
[INFO] --> Scanning for dependencies using commit ids
[INFO] Gathering information on each dependency
[INFO] --> This may take a moment. Especially on a codebase with many dependencies
[INFO] --> Gathering release information for dependencies
[INFO] --> Looking for dependency imports where versions are commit ids
[INFO] Here are some suggestions...
[INFO] The package github.com/urfave/cli appears to have Semantic Version releases (http://semver.org).
[INFO] The latest release is v1.19.1. You are currently not using a release. Would you like
[INFO] to use this release? Yes (Y) or No (N)
Y
[INFO] Would you like to remember the previous decision and apply it to future
[INFO] dependencies? Yes (Y) or No (N)
Y
[INFO] Updating github.com/urfave/cli to use the release v1.19.1 instead of no release
[INFO] The package github.com/urfave/cli appears to use semantic versions (http://semver.org).
[INFO] Would you like to track the latest minor or patch releases (major.minor.patch)?
[INFO] Tracking minor version releases would use '>= 1.19.1, < 2.0.0' ('^1.19.1'). Tracking patch version
[INFO] releases would use '>= 1.19.1, < 1.20.0' ('~1.19.1'). For more information on Glide versions
[INFO] and ranges see https://glide.sh/docs/versions
[INFO] Minor (M), Patch (P), or Skip Ranges (S)?
P
[INFO] Would you like to remember the previous decision and apply it to future
[INFO] dependencies? Yes (Y) or No (N)
Y
[INFO] Updating github.com/urfave/cli to use the range ~1.19.1 instead of commit id v1.19.1
[INFO] Configuration changes have been made. Would you like to write these
[INFO] changes to your configuration file? Yes (Y) or No (N)
Y
[INFO] Writing updates to configuration file (glide.yaml)
[INFO] You can now edit the glide.yaml file.:
[INFO] --> For more information on versions and ranges see https://glide.sh/docs/versions/
[INFO] --> For details on additional metadata see https://glide.sh/docs/glide.yaml/
$ ll
glide.yaml
$ cat glide.yaml
package: foor
import: []

在初始化过程中, glide 会询问一些问题。
glide.yaml记载了依赖包的列表及其更新规则,每次执行 glide up 时,都会按照指定的规则(如只下载补丁(patch)不下载升级(minor))下载新版。


一个完整的gilde.yaml


package: foor
homepage: https://github.com/qiangmzsx
license: MIT
owners:
- name: qiangmzsx
email: qiangmzsx@hotmail.com
homepage: https://github.com/qiangmzsx
# 去除包
ignore:
- appengine
- golang.org/x/net
# 排除目录
excludeDirs:
- node_modules
# 导入包
import:
- package: github.com/astaxie/beego
version: 1.8.0
- package: github.com/coocood/freecache
- package: github.com/garyburd/redigo/redis
- package: github.com/go-sql-driver/mysql
- package: github.com/bitly/go-simplejson
- package: git.oschina.net/qiangmzsx/beegofreecache
testImport:
- package: github.com/smartystreets/goconvey
subpackages:
- convey

很多人看着yaml很不习惯,没事,我转一下json给大家看看。


{
"excludeDirs": [
"node_modules"
],
"owners": [
{
"homepage": "https://github.com/qiangmzsx",
"name": "qiangmzsx",
"email": "qiangmzsx@hotmail.com"
}
],

"license": "MIT",
"package": "foor",
"ignore": [
"appengine",
"golang.org/x/net"
],
"import": [
{
"version": "1.8.0",
"package": "github.com/astaxie/beego"
},
{
"package": "github.com/coocood/freecache"
},
{
"package": "github.com/garyburd/redigo/redis"
},
{
"package": "github.com/go-sql-driver/mysql"
},
{
"package": "github.com/bitly/go-simplejson"
},
{
"package": "git.oschina.net/qiangmzsx/beegofreecache"
}
],
"testImport": [
{
"subpackages": [
"convey"
],
"package": "github.com/smartystreets/goconvey"
}
],
"homepage": "https://github.com/qiangmzsx"
}

版本号指定规则


=: equal (aliased to no operator)
!=: not equal
>: greater than
<: less than
>=: greater than or equal to
<=: less than or equal to

1.2 - 1.4.5 which is equivalent to >= 1.2, <= 1.4.5
2.3.4 - 4.5 which is equivalent to >= 2.3.4, <= 4.5
1.2.x is equivalent to >= 1.2.0, < 1.3.0

>= 1.2.x is equivalent to >= 1.2.0
<= 2.x is equivalent to < 3
* is equivalent to >= 0.0.0

~1.2.3 is equivalent to >= 1.2.3, < 1.3.0
~1 is equivalent to >= 1, < 2
~2.3 is equivalent to >= 2.3, < 2.4
~1.2.x is equivalent to >= 1.2.0, < 1.3.0
~1.x is equivalent to >= 1, < 2

^1.2.3 is equivalent to >= 1.2.3, < 2.0.0
^1.2.x is equivalent to >= 1.2.0, < 2.0.0
^2.3 is equivalent to >= 2.3, < 3
^2.x is equivalent to >= 2.0.0, < 3

''指定版本报错,需要用''指定的可以不填写


安装依赖 (glide install)


glide.yaml我们已经准备好了,现在就改安装一下试试。


$ glide install
[ERROR] Failed to parse /home/users/xxxx/golang/src/foor/glide.yaml: yaml: invalid leading UTF-8 octet

报错了!别担心看看你的yaml文件是否为utf-8编码,不是就转换一下就好啦!


$ glide install
[INFO] Lock file (glide.lock) does not exist. Performing update.
[INFO] Downloading dependencies. Please wait...
[INFO] --> Fetching updates for github.com/go-sql-driver/mysql
[INFO] --> Fetching updates for github.com/astaxie/beego
[INFO] --> Fetching updates for github.com/coocood/freecache
[INFO] --> Fetching updates for git.oschina.net/qiangmzsx/beegofreecache
[INFO] --> Fetching updates for github.com/bitly/go-simplejson
[INFO] --> Fetching updates for github.com/garyburd/redigo
[INFO] --> Fetching updates for github.com/smartystreets/goconvey
[INFO] --> Detected semantic version. Setting version for github.com/astaxie/beego to v1.8.0
[INFO] Resolving imports
[INFO] Downloading dependencies. Please wait...
[INFO] Setting references for remaining imports
[INFO] Exporting resolved dependencies...
[INFO] --> Exporting github.com/astaxie/beego
[INFO] --> Exporting github.com/coocood/freecache
[INFO] --> Exporting github.com/bitly/go-simplejson
[INFO] --> Exporting github.com/go-sql-driver/mysql
[INFO] --> Exporting github.com/garyburd/redigo
[INFO] --> Exporting github.com/smartystreets/goconvey
[INFO] --> Exporting git.oschina.net/qiangmzsx/beegofreecache
[INFO] Replacing existing vendor dependencies
[INFO] Project relies on 6 dependencies.
$ ll
total 12
glide.lock
glide.yaml
vendor
$ ll vendor/
git.oschina.net
github.com

看到glide.look了吗,这个文件记载了依赖包确定的revision, 下次再执行 glide install 时,会直接读这个文件下载确定的版本。


升级版本 (glide up)


glide up 会按照语义化版本规则更新依赖包代码,开发过程中如果需要使用新版代码,可以执行这个命令:
修改一下glide.yaml中的一个Package.


- package: github.com/astaxie/beego
version: 1.8.3

执行glide up。


$ glide up
[INFO] Downloading dependencies. Please wait...
[INFO] --> Fetching updates for git.oschina.net/qiangmzsx/beegofreecache
[INFO] --> Fetching updates for github.com/garyburd/redigo
[INFO] --> Fetching updates for github.com/go-sql-driver/mysql
[INFO] --> Fetching updates for github.com/astaxie/beego
[INFO] --> Fetching updates for github.com/bitly/go-simplejson
[INFO] --> Fetching updates for github.com/coocood/freecache
[INFO] --> Fetching updates for github.com/smartystreets/goconvey
[INFO] --> Detected semantic version. Setting version for github.com/astaxie/beego to v1.8.3
[INFO] Resolving imports
[INFO] Downloading dependencies. Please wait...
[INFO] Setting references for remaining imports
[INFO] Exporting resolved dependencies...
[INFO] --> Exporting github.com/astaxie/beego
[INFO] --> Exporting github.com/bitly/go-simplejson
[INFO] --> Exporting github.com/garyburd/redigo
[INFO] --> Exporting github.com/go-sql-driver/mysql
[INFO] --> Exporting github.com/coocood/freecache
[INFO] --> Exporting github.com/smartystreets/goconvey
[INFO] --> Exporting git.oschina.net/qiangmzsx/beegofreecache
[INFO] Replacing existing vendor dependencies
[INFO] Project relies on 6 dependencies.

添加并下载依赖 (glide get)


除了自动从代码中解析 import 外,glide 还可以通过 glide get 直接下载代码中没有的依赖,与 go get 的用法基本一致:


$ glide get github.com/orcaman/concurrent-map
[INFO] Preparing to install 1 package.
[INFO] Attempting to get package github.com/orcaman/concurrent-map
[INFO] --> Gathering release information for github.com/orcaman/concurrent-map
[INFO] --> Adding github.com/orcaman/concurrent-map to your configuration
[INFO] Downloading dependencies. Please wait...
[INFO] --> Fetching updates for github.com/garyburd/redigo
[INFO] --> Fetching updates for github.com/astaxie/beego
[INFO] --> Fetching updates for github.com/go-sql-driver/mysql
[INFO] --> Fetching updates for git.oschina.net/qiangmzsx/beegofreecache
[INFO] --> Fetching updates for github.com/bitly/go-simplejson
[INFO] --> Fetching github.com/orcaman/concurrent-map
[INFO] --> Fetching updates for github.com/coocood/freecache
[INFO] --> Fetching updates for github.com/smartystreets/goconvey
[INFO] Resolving imports
[INFO] Downloading dependencies. Please wait...
[INFO] --> Detected semantic version. Setting version for github.com/astaxie/beego to v1.8.3
[INFO] Exporting resolved dependencies...
[INFO] --> Exporting github.com/smartystreets/goconvey
[INFO] --> Exporting github.com/garyburd/redigo
[INFO] --> Exporting github.com/go-sql-driver/mysql
[INFO] --> Exporting github.com/orcaman/concurrent-map
[INFO] --> Exporting github.com/astaxie/beego
[INFO] --> Exporting github.com/bitly/go-simplejson
[INFO] --> Exporting github.com/coocood/freecache
[INFO] --> Exporting git.oschina.net/qiangmzsx/beegofreecache
[INFO] Replacing existing vendor dependencies

使用镜像 (glide mirror)


[WARN]  Unable to checkout golang.org/x/crypto
[ERROR] Update failed for golang.org/x/crypto: Cannot detect VCS
[ERROR] Failed to do initial checkout of config: Cannot detect VCS

这几行信息估计很多人都是遇到过的。在我天朝或者在公司内部都可能不能访问一些站点,导致很Golang的依赖包不能通过go get下载。此时也就是glide大发神威的时候到了,可以通过配置将墙了的版本库 URL 映射到没被墙的 URL,甚至也可以映射到本地版本库。
将golang.org映射到github:
修改glide.yaml加入


- package: golang.org/x/crypto

如果你的网络可以访问就不需要使用glide镜像功能,可以跳过。


$ glide mirror set golang.org/x/crypto github.com/golang/crypto
[INFO] golang.org/x/crypto being set to github.com/golang/crypto
[INFO] mirrors.yaml written with changes
$ glide up
[INFO] Loading mirrors from mirrors.yaml file
[INFO] Downloading dependencies. Please wait...
[INFO] --> Fetching updates for github.com/orcaman/concurrent-map
[INFO] --> Fetching golang.org/x/crypto
[INFO] --> Fetching updates for github.com/astaxie/beego
[INFO] --> Fetching updates for github.com/go-sql-driver/mysql
[INFO] --> Fetching updates for github.com/garyburd/redigo
[INFO] --> Fetching updates for github.com/coocood/freecache
[INFO] --> Fetching updates for github.com/bitly/go-simplejson
[INFO] --> Fetching updates for git.oschina.net/qiangmzsx/beegofreecache
[INFO] --> Fetching updates for github.com/smartystreets/goconvey
[INFO] --> Detected semantic version. Setting version for github.com/astaxie/beego to v1.8.3
[INFO] Resolving imports
[INFO] Downloading dependencies. Please wait...
[INFO] Setting references for remaining imports
[INFO] Exporting resolved dependencies...
[INFO] --> Exporting github.com/astaxie/beego
[INFO] --> Exporting github.com/coocood/freecache
[INFO] --> Exporting github.com/smartystreets/goconvey
[INFO] --> Exporting github.com/garyburd/redigo
[INFO] --> Exporting github.com/go-sql-driver/mysql
[INFO] --> Exporting github.com/bitly/go-simplejson
[INFO] --> Exporting github.com/orcaman/concurrent-map
[INFO] --> Exporting golang.org/x/crypto
[INFO] --> Exporting git.oschina.net/qiangmzsx/beegofreecache
[INFO] Replacing existing vendor dependencies
[INFO] Project relies on 8 dependencies.
$ ll vendor/
git.oschina.net
github.com
golang.org

终于看到golang.org啦!!!
细心的你一定已经发现了


[INFO]  mirrors.yaml written with changes

说明执行glide mirror时候镜像配置写入到的是$HOME/.glide/mirrors.yaml中,打开看看。


repos:
- original: golang.org/x/crypto
repo: github.com/golang/crypto

还可以映射到本地目录。
推荐大家可以去https://www.golangtc.com/download/package下载很多Golang类库。
现在我去下载了:https://www.golangtc.com/static/download/packages/golang.org.x.text.tar.gz,解压到本地目录/home/users/qiangmzsx/var/golang/golang.org/x/text


$ glide mirror set golang.org/x/text /home/users/qiangmzsx/var/golang/golang.org/x/text
[INFO] golang.org/x/text being set to /home/users/qiangmzsx/var/golang/golang.org/x/text
[INFO] mirrors.yaml written with changes
$ glide up
[INFO] Loading mirrors from mirrors.yaml file
[INFO] Downloading dependencies. Please wait...
[INFO] --> Fetching golang.org/x/text
[INFO] --> Fetching updates for github.com/garyburd/redigo
[INFO] --> Fetching updates for git.oschina.net/qiangmzsx/beegofreecache
[INFO] --> Fetching updates for github.com/astaxie/beego
[INFO] --> Fetching updates for github.com/bitly/go-simplejson
[INFO] --> Fetching updates for github.com/go-sql-driver/mysql
[INFO] --> Fetching updates for github.com/coocood/freecache
[INFO] --> Fetching updates for github.com/orcaman/concurrent-map
[INFO] --> Fetching updates for golang.org/x/crypto
[INFO] --> Fetching updates for github.com/smartystreets/goconvey
[INFO] --> Detected semantic version. Setting version for github.com/astaxie/beego to v1.8.3
[INFO] Resolving imports
[INFO] Downloading dependencies. Please wait...
[INFO] Setting references for remaining imports
[INFO] Exporting resolved dependencies...
[INFO] --> Exporting github.com/astaxie/beego
[INFO] --> Exporting github.com/go-sql-driver/mysql
[INFO] --> Exporting github.com/bitly/go-simplejson
[INFO] --> Exporting github.com/coocood/freecache
[INFO] --> Exporting github.com/smartystreets/goconvey
[INFO] --> Exporting github.com/garyburd/redigo
[INFO] --> Exporting github.com/orcaman/concurrent-map
[INFO] --> Exporting golang.org/x/text
[INFO] --> Exporting golang.org/x/crypto
[INFO] --> Exporting git.oschina.net/qiangmzsx/beegofreecache
[INFO] Replacing existing vendor dependencies
[INFO] Project relies on 9 dependencies.

全局选项


运行glide,在最后就可以看到


GLOBAL OPTIONS:
--yaml value, -y value Set a YAML configuration file. (default: "glide.yaml")
--quiet, -q Quiet (no info or debug messages)
--debug Print debug verbose informational messages
--home value The location of Glide files (default: "/home/users/qiangmzsx/.glide") [$GLIDE_HOME]
--tmp value The temp directory to use. Defaults to systems temp [$GLIDE_TMP]
--no-color Turn off colored output for log messages
--help, -h show help
--version, -v print the version

如果大家想把glide的yaml文件换别的默认名称可以执行


 $ glide -y qiangmzsx.yaml

在官网中会看到一个GLIDE_HOME变量,该变量就是/home/users/qiangmzsx/.glide
这个目录之前有提到过,除了包含有mirrors.yaml还有一个很重要的目录cache本地 cache,每次更新代码时, glide 都会在本地保存 cache,以备下次 glide install 使用 。


GLIDE_HOME可以通过如下命令修改。


 $ glide  --home /home/glide 

总结


除了上述说到的功能,glide还有很多好的功能,后续有机会在写出来吧。

总结一下,glide是一款功能丰富,完全满足需求的依赖管理工具,强烈大家使用。

beego & bee 1.9.0 released

astaxie 发表了文章 • 0 个评论 • 673 次浏览 • 2017-07-19 01:07 • 来自相关话题

beego:

  1. Fix the new repo address for casbin #2654
  2. Fix cache/memory fatal error: concurrent map iteration a... 查看全部

beego:



  1. Fix the new repo address for casbin #2654

  2. Fix cache/memory fatal error: concurrent map iteration and map write #2726

  3. AddAPPStartHook func modify #2724

  4. Fix panic: sync: negative WaitGroup counter #2717

  5. incorrect error rendering (wrong status) #2712

  6. validation: support int64 int32 int16 and int8 type #2728

  7. validation: support required option for some struct tag valids #2741

  8. Fix big form parse issue #2725

  9. File log add RotatePerm #2683

  10. Fix Oracle placehold #2749

  11. Supported gzip for req.Header has Content-Encoding: gzip #2754

  12. Add new Database Migrations #2744

  13. Beego auto generate sort ControllerComments #2766

  14. added statusCode and pattern to FilterMonitorFunc #2692

  15. fix the bugs in the "ParseBool" function in the file of config.go #2740


Bee



  1. Added MySQL year data type #443

  2. support multiple http methods #445

  3. The DDL migration can now be generated by adding a -ddl and a proper "alter" or "create" as argument value. #455

  4. Fix: docs generator skips everything containing 'vendor' #454

  5. get these tables information in custom the option #441

  6. read ref(pk) #444

  7. Add command bee server to server static folder.


https://github.com/astaxie/beego/pull/2771

给httprouter添加pprof功能

narutoinfo 发表了文章 • 0 个评论 • 294 次浏览 • 2017-07-18 19:40 • 来自相关话题

给httprouter添加pprof

1:获取包

go get github.com/feixiao/htt... 			查看全部
					

给httprouter添加pprof


1:获取包


go get github.com/feixiao/httpprof

2:进入所在目录,获取依赖


 govendor sync

3:编译运行example


go build

4:外部项目添加使用,只需要参考example的使用即可


func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprint(w, "Welcome!\n")
}

func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}

func main() {
router := httprouter.New()

// 在原来的httprouter的使用基础只是添加了这一句代码
router = httpprof.WrapRouter(router)

router.GET("/", Index)
router.GET("/hello/:name", Hello)

log.Fatal(http.ListenAndServe(":8080", router))
}

【Go大咖说】 分享第一期——姜家志《比特币、区块链和Go开发》

astaxie 发表了文章 • 9 个评论 • 1648 次浏览 • 2017-07-17 16:37 • 来自相关话题

GoCN社区最近打算推出全新的栏目《Go大咖说》,第一期我们邀请到了来自比特大陆的高级工程师姜家志给我们带来分享《比特币、区块链和Go开发》

个人介绍: 姜家志,2013年开始接触比特币,之后开发了比太钱包,现在在比特大陆从事比特币相关的开... 查看全部

GoCN社区最近打算推出全新的栏目《Go大咖说》,第一期我们邀请到了来自比特大陆的高级工程师姜家志给我们带来分享《比特币、区块链和Go开发》


个人介绍:
姜家志,2013年开始接触比特币,之后开发了比太钱包,现在在比特大陆从事比特币相关的开发工作。



大纲:



  • 比特币是什么

  • 区块链是什么以及区块链行业现状

  • Go语言在区块链行业的应用以及优势


我们的分享会在我们的Go实战群直播,会同步转发到全部的实战群,大家可以加微信群或者QQ群,


直播时间:周二(2017-07-18) 晚上8点开始


微信:请加fuxiaohei,备注:Go实战群
QQ: 148647580


后续会整理成文发布在Go中国微信公众号,大家可以关注我们的公众号:

golang结构体json的时间格式化解决方案

qiangmzsx 发表了文章 • 4 个评论 • 907 次浏览 • 2017-07-15 23:40 • 来自相关话题

最近开发项目时候发现一个结构体的Json转换的时间格式问题。 即这种1993-01-01T20:08:23.000000028+08:00 这种表示UTC方法。从我们习惯来说,更喜欢希望的是 1993-01-01 20:08:23这种格式。 重新复现代码... 查看全部

最近开发项目时候发现一个结构体的Json转换的时间格式问题。
即这种1993-01-01T20:08:23.000000028+08:00 这种表示UTC方法。从我们习惯来说,更喜欢希望的是
1993-01-01 20:08:23这种格式。
重新复现代码如下:



package main

import (
"time"
"encoding/json"
)

type Student struct {
Name string `json:"name"`
Brith time.Time `json:"brith"`
}

func main() {
stu:=Student{
Name:"qiangmzsx",
Brith:time.Date(1993, 1, 1, 20, 8, 23, 28, time.Local),
}

b,err:=json.Marshal(stu)
if err!=nil {
println(err)
}

println(string(b))//{"name":"qiangmzsx","brith":"1993-01-01T20:08:23.000000028+08:00"}
}

遇到这样的问题,那么Golang是如何解决的呢?
有两种解决方案,下面我们一个个来看看。


通过time.Time类型别名


type JsonTime time.Time
// 实现它的json序列化方法
func (this JsonTime) MarshalJSON() ([]byte, error) {
var stamp = fmt.Sprintf("\"%s\"", time.Time(this).Format("2006-01-02 15:04:05"))
return []byte(stamp), nil
}
type Student1 struct {
Name string `json:"name"`
Brith JsonTime `json:"brith"`
}
func main() {

stu1:=Student1{
Name:"qiangmzsx",
Brith:JsonTime(time.Date(1993, 1, 1, 20, 8, 23, 28, time.Local)),
}
b1,err:=json.Marshal(stu1)
if err!=nil {
println(err)
}

println(string(b1))//{"name":"qiangmzsx","brith":"1993-01-01 20:08:23"}
}

使用结构体组合方式


相较于第一种方式,该方式显得复杂一些,我也不是很推荐使用,就当做是一个扩展教程吧。


type Student2 struct {
Name string `json:"name"`
// 一定要将json的tag设置忽略掉不解析出来
Brith time.Time `json:"-"`
}
// 实现它的json序列化方法
func (this Student2) MarshalJSON() ([]byte, error) {
// 定义一个该结构体的别名
type AliasStu Student2
// 定义一个新的结构体
tmpStudent:= struct {
AliasStu
Brith string `json:"brith"`
}{
AliasStu:(AliasStu)(this),
Brith:this.Brith.Format("2006-01-02 15:04:05"),
}
return json.Marshal(tmpStudent)
}
func main() {
stu2:=Student2{
Name:"qiangmzsx",
Brith:time.Date(1993, 1, 1, 20, 8, 23, 28, time.Local),
}

b2,err:=json.Marshal(stu2)
if err!=nil {
println(err)
}

println(string(b2))//{"name":"qiangmzsx","brith":"1993-01-01 20:08:23"}
}

该方法使用了Golang的结构体的组合方式,可以实现OOP的继承,也是体现Golang灵活。


整体代码


下面把上面的代码组成整体贴出来。



package main

import (
"time"
"encoding/json"
//"fmt"
"fmt"
)

type Student struct {
Name string `json:"name"`
Brith time.Time `json:"brith"`
}

type JsonTime time.Time
// 实现它的json序列化方法
func (this JsonTime) MarshalJSON() ([]byte, error) {
var stamp = fmt.Sprintf("\"%s\"", time.Time(this).Format("2006-01-02 15:04:05"))
return []byte(stamp), nil
}
type Student1 struct {
Name string `json:"name"`
Brith JsonTime `json:"brith"`
}

type Student2 struct {
Name string `json:"name"`
// 一定要将json的tag设置忽略掉不解析出来
Brith time.Time `json:"-"`
}
// 实现它的json序列化方法
func (this Student2) MarshalJSON() ([]byte, error) {
// 定义一个该结构体的别名
type AliasStu Student2
// 定义一个新的结构体
tmpStudent:= struct {
AliasStu
Brith string `json:"brith"`
}{
AliasStu:(AliasStu)(this),
Brith:this.Brith.Format("2006-01-02 15:04:05"),
}
return json.Marshal(tmpStudent)
}

func main() {
stu:=Student{
Name:"qiangmzsx",
Brith:time.Date(1993, 1, 1, 20, 8, 23, 28, time.Local),
}

b,err:=json.Marshal(stu)
if err!=nil {
println(err)
}

println(string(b))//{"name":"qiangmzsx","brith":"1993-01-01T20:08:23.000000028+08:00"}

println("===================")

stu1:=Student1{
Name:"qiangmzsx",
Brith:JsonTime(time.Date(1993, 1, 1, 20, 8, 23, 28, time.Local)),
}
b1,err:=json.Marshal(stu1)
if err!=nil {
println(err)
}

println(string(b1))//{"name":"qiangmzsx","brith":"1993-01-01 20:08:23"}

println("===================")
stu2:=Student2{
Name:"qiangmzsx",
Brith:time.Date(1993, 1, 1, 20, 8, 23, 28, time.Local),
}

b2,err:=json.Marshal(stu2)
if err!=nil {
println(err)
}

println(string(b2))//{"name":"qiangmzsx","brith":"1993-01-01 20:08:23"}
}

值得一提的是,对任意struct增加 MarshalJSON ,UnmarshalJSON , String 方法,实现自定义json输出格式与打印方式。

Gopher社区的第一件众筹T恤来了

CodyGuo 回复了问题 • 6 人关注 • 7 个回复 • 963 次浏览 • 2017-06-29 09:10 • 来自相关话题