标签 Gopher 下的文章

制作go-talks.appspot.com应用镜像

Go语言号称面向工程:对工程目录组织、代码风格(gofmt)、文档(生成)都制定的相应的“标准”,并提供了相应的工具帮助开发者满足这些工程specs。

gofmt用于格式化代码,形成统一代码风格。
godoc.org用于查看标准库或repo的doc。
go-talks.appspot.com则是用来查看go slide。

godocgo-talks这种以服务形式提供文档查看的形式不得不说是golang的又一创新。

这几年Golang的开发者们是非常勤奋的,为了推广Golang,他们撰写博客,编写文档,并四处布道,积累下许多有价值的文档,这些文档多以 Gopher所特有的present格式存在着,这些 present格式的文档以.slide、.article或.ext为后缀,通过go-talks.appspot.com提供的present渲染服 务浏览,并且支持github.com repo中的slide文件。Go开发者们只需要将自己写好的slide文件存放在自己github.com上的repo中,就可以随时随地在世界各地打 开这类present文件为大家布道了。

不过来到中国大陆后,事情就没那么顺利了,因为appspot.com在大陆是无法直接访问的,你懂得哦。为了观看这些大牛的slide,内地的Go程序员只能四处寻找出(fan)国(qiang)工具,但这毕竟不是十分方便。

上周末@开发者头条分享了“why Go is fast? [Slide] High performance servers without the event loop (Golang)”这个Dave Cheney在O'Reilly OSCON上分享的Go slide,但因为链接被qiang,无法直接观看。于是就想到能不能制作一个go-talks.appspot.com的镜像站点,让国内Go程序员也 能享受些福利呢?于是乎我就开始了镜像制作的探索过程。

一、在本地搭建go-talks.appspot.com镜像

present格式类似于markup,是一种标记语言,只是present格式更多用来制作slide。

golang.org/x/tools/present提供了present文件格式的解析库,最初本以为需要从头开始写server,并利用 present库解析,写模板和javascript实现类似翻页等功能呢。但后来居然在gddo repo,也就是godoc.org的源码工程中找到了go-talks.appsport.com站点的源码: talksapp。

不过talksapp是运行在google app engine上的应用,要将其直接运行在standalone server上是否可行呢?是否需要改造?这些都是未知数,不过有了源码自然是很好的。我们先来试试这个程序是否能在本地运行起来。

首先下载gddo repo:

$go get github.com/golang/gddo/
$cd $GOPATH/src/github.com/golang/gddo/talksapp

talksapp的主页文档似乎有些out-dated,我并没有找到config.go.template。   

但按照文档要求,需要下载Go App Engine SDK,这个需要搭梯子。在https://cloud.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go页面根据您的平台版本下载最新Go SDK版本。解压后,先放在那里不动。

根据talksapp文档,第三步就应该是sh setup.sh。setup.sh中get两个repo均在qiang外,需要梯子才能下载。

setup.sh正确执行之后,我们用go_appengine下dev_appserver.py来运行talksapp:

$dev_appserver.py ~/Test/GoToolsProjects/src/github.com/golang/gddo/talksapp
INFO     2015-07-27 08:25:09,076 api_server.py:205] Starting API server at: http://localhost:51801
INFO     2015-07-27 08:25:09,080 dispatcher.py:197] Starting module "default" running at: http://localhost:8080
INFO     2015-07-27 08:25:09,083 admin_server.py:118] Starting admin server at: http://localhost:8000
/Users/tony/Test/GoToolsProjects/src/appengine/google/appengine/tools/devappserver2/mtime_file_watcher.py:115: UserWarning: There are too many files in your application for changes in all of them to be monitored. You may have to restart the development server to see some changes to your files.
  'There are too many files in your application for '
ERROR    2015-07-27 08:25:11,941 http_runtime.py:380] bad runtime process port ['']
2015/07/27 08:25:11 secret.json needs to define ClientID and ClientSecret

使用浏览器访问localhost:8080,得到的页面中也只是有些错误日志,日志与上面最后两行相同。从错误日志来看,似乎需要配置一下secret.json这个文件,至少ClientID和ClientSecret不能为空。

我就随意配置两个值(这两个值似乎应该是github.com的账号和密码,用于OAuth2,如果随意配置无法成功,那建议配置上真实的账号和密码),看看是否可以访问:

{
    "ClientID": "xx",
    "ClientSecret": "yy"
}

这回再执行talksapp就不再报错了。用浏览器访问localhost:8080, go-talks的页面顺利正常显示出来!看来在本地是可以运行的哦!

我们再来测试一下访问github.com上的一个slide,地址如下:

http://localhost:8080/github.com/gophercon/2015-talks/Dmitry_Vyukov_-_Go_Dynamic_Tools/tools.slide

加载有些慢,有些时候提示:
  
   canceled: Deadline exceeded (timeout)

试了几次后,居然加载成功了!又试了几个slide,除了有些慢,都是成功的。看来talksapp是可以在standalone主机上运行的。

二、在vps上部署go-talks镜像

虽然在本机上可以正常浏览Golang大牛们的slide的了,但毕竟放在local上不是很方便,离开这台机器又无法访问了。广大内地go程序员们依旧 生活在“水深火热”中,在“分享经济”兴起的今天,我想也力所能及的做些贡献吧。于是想到了将这个镜像部署到我的blog vps上,这样大家就可以自由浏览golang slide了。

我的vps放在了DigitalOcean上(Ubuntu 14.04 server amd64),配置较低,平时仅仅作为blog托管主机。不过放一个go-talks镜像应该还是可以满足的,也可以更充分“压榨”一下DO的资源。

于是乎,我就按照上面的步骤将talksapp安装在了vps上。考虑到talksapp作为一个守护进程,又安装了supervisor对其进行管理:

/etc/supervisor/conf.d/go-talks.conf
[program:go-talks]
environment=GOROOT=/root/.bin/go142
environment=GOPATH=/root/go-talks
directory=/root/go-talks/src/github.com/golang/gddo/talksapp
command=/root/go-talks/go_appengine/goapp serve
autostart=true
autorestart=true
startsecs=3

这里没有使用dev_appserver.py,而是用了两位一个程序goapp,通过在talksapp目录下执行goapp serve来启动这个"GAE"服务。现在vps上启动了localhost:8080服务,但外面的人还是无法访问到这个服务。

如果要对外发布这个服务,我需要一个域名,考虑到自己已有的blog域名,为了快速开通服务,我添加了一个二级域名:go-talks.tonybai.com,模仿go-talks.appspot.com。

我们还需要调整一下apache2 server。原先的apache2 server只是为blog(wordpress)提供服务,现在我们需要将go-talks.tonybai.com映射到主机内部的8080端口服务 上,这就需要开启apache2的反向代理功能,对apache2也不是很熟悉,于是在网上找到了一段配置,补充到/etc/apache2 /apache2.conf中:

<VirtualHost *:80>
    ServerName go-talks.tonybai.com
    ProxyPreserveHost On
    ProxyRequests Off
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
</VirtualHost>

Include /etc/phpmyadmin/apache.conf

重启apache2,出现下面错误:

root@tonybai:/etc/apache2# sudo service apache2 restart
 * Restarting web server apache2          [fail]
 * The apache2 configtest failed.
Output of config test was:
AH00526: Syntax error on line 85 of /etc/apache2/apache2.conf:
Invalid command 'ProxyPreserveHost', perhaps misspelled or defined by a module not included in the server configuration
Action 'configtest' failed.
The Apache error log may have more information.

似乎是反向代理需要更多apache2 module才能运行,于是:

sudo a2enmod proxy
sudo a2enmod proxy_http

再重启apache2,这回ok了。

在DNS服务商内已经添加了go-talks.tonybai.com这个域名,但由于国内DNS生效时间较慢,为了测试服务是否ok,我修改了 hosts文件,手动将go-talks.tonybai.com指向vps的公网地址。接下来访问go-talks.tonybai.com这个地址, 镜像制作成功了! 又测试了几个slide,均正确生成!速度稍慢,那是因为vps的一般延迟都在2600ms左右。

我的VPS性能不高,大家访问时也许会感觉较慢,但有胜于无!

最后再重申一下go-talks.tonybai.com的使用方法:

如果某个分享链接为:go-talks.appspot.com/xxx/yy/zz/foo.slide,那么将该地址替换为:go- talks.tonybai.com/xxx/yy/zz/foo.slide即可。也就是将appspot换成tonybai,其他不变。

该服务已经利用监控宝监控起来了,如果出现问题(比如网络或资源不足的问题),我会及时处理。但这里不保证100%可用哦!希望大家友好使用,不要拍砖!

Go 1.5中值得关注的几个变化

GopherCon2015开幕之 际,Google Go Team终于放出了Go 1.5Beta1版本的安装包。在go 1.5Beta1的发布说明中,Go Team也诚恳地承认Go 1.5将打破之前6个月一个版本的发布周期,这是因为Go 1.5变动太大,需要更多时间来准备这次发布(fix bug, Write doc)。关于Go 1.5的变化,之前Go Team staff在各种golang技术会议的slide  中暴露不少,包括:

- 编译器和运行时由C改为Go(及少量汇编语言)重写,实现了Go的self Bootstrap(自举)
- Garbage Collector优化,大幅降低GC延迟(Stop The World),实现Gc在单独的goroutine中与其他user goroutine并行运行。
- 标准库变更以及一些go tools的引入。

每项变动都会让gopher激动不已。但之前也只是激动,这次beta1出来后,我们可以实际体会一下这些变动带来的“快感”了。Go 1.5beta1的发布文档目前还不全,有些地方还有“待补充”字样,可能与最终go 1.5发布时的版本有一定差异,不过大体内容应该是固定不变的了。这篇文章就想和大家一起浅显地体验一下go 1.5都给gophers们带来了哪些变化吧。

一、语言

【map literal】

go 1.5依旧兼容Go 1 language specification,但修正了之前的一个“小疏忽”。

Go 1.4及之前版本中,我们只能这么来写代码:

//testmapliteral.go
package main

import (
    "fmt"
)

type Point struct {
    x int
    y int
}

func main() {
    var sl = []Point{{3, 4}, {5, 6}}
    var m = map[Point]string{
        Point{3,4}:"foo1",
        Point{5,6}:"foo2",
    }
    fmt.Println(sl)
    fmt.Println(m)
}

可以看到,对于Point这个struct来说,在初始化一个slice时,slice value literal中无需显式的带上元素类型Point,即

var sl = []Point{{3, 4}, {5, 6}}

而不是

var sl = []Point{Point{3, 4}, Point{5, 6}}

但当Point作为map类型的key类型时,初始化map时则要显式带上元素类型Point。Go team承认这是当初的一个疏忽,在本次Go 1.5中将该问题fix掉了。也就是说,下面的代码在Go 1.5中可以顺利编译通过:

func main() {
    var sl = []Point{{3, 4}, {5, 6}}
    var m = map[Point]string{
        {3,4}:"foo1",
        {5,6}:"foo2",
    }
    fmt.Println(sl)
    fmt.Println(m)
}

【GOMAXPROCS】

就像这次GopherCon2015上现任Google Go project Tech Lead的Russ Cox的开幕Keynote中所说的那样:Go目标定位于高度并发的云环境。Go 1.5中将标识并发系统线程个数的GOMAXPROCS的初始值由1改为了运行环境的CPU核数。

// testgomaxprocs.go
package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println(runtime.GOMAXPROCS(-1))
    fmt.Println(runtime.NumGoroutine())
}

这个代码在Go 1.4下(Mac OS X 4核)运行结果是:

$go run testgomaxprocs.go
1
4

而在go 1.5beta1下,结果为:

$go run testgomaxprocs.go
4
4

二、编译

【简化跨平台编译】

1.5之前的版本要想实现跨平台编译,需要到$GOROOT/src下重新执行一遍make.bash,执行前设置好目标环境的环境变量(GOOS和 GOARCH),Go 1.5大大简化这个过程,使得跨平台编译几乎与普通编译一样简单。下面是一个简单的例子:

//testcrosscompile.go
package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println(runtime.GOOS)
}

在我的Mac上,本地编译执行:
$go build -o testcrosscompile_darwin testcrosscompile.go
$testcrosscompile_darwin
darwin

跨平台编译linux amd64上的目标程序:

$GOOS=linux GOARCH=amd64 go build -o testcrosscompile_linux testcrosscompile.go

上传testcrosscompile_linux到ubuntu 14.04上执行:
$testcrosscompile_linux
linux

虽然从用户角度跨平台编译命令很简单,但事实是go替你做了很多事情,我们可以通过build -x -v选项来输出编译的详细过程,你会发现go会先进入到$GOROOT/src重新编译runtime.a以及一些平台相关的包。编译输出的信息 太多,这里就不贴出来了。但在1.5中这个过程非常快(10秒以内),与1.4之前版本的跨平台编译相比,完全不是一个级别,这也许就是编译器用Go重写完的好处之一吧。

除了直接使用go build,我们还可以使用go tool compile和go tool link来编译程序,实际上go build也是调用这两个工具完成编译过程的。

$go tool compile testcrosscompile.go
testcrosscompile.o
$go tool link testcrosscompile.o
a.out
$a.out
darwin

go 1.5移除了以前的6a,6l之类的编译连接工具,将这些工具整合到go tool中。并且go tool compile的输出默认改为.o文件,链接器输出默认改为了a.out。

【动态共享库】

个人不是很赞同Go语言增加对动态共享库的支持,.so和.dll这类十多年前的技术在如今内存、磁盘空间都“非常大”的前提下,似乎已经失去了以往的魅 力。并且动态共享库所带来的弊端:"DLL hell"会让程序后续的运维痛苦不已。Docker等轻量级容器的兴起,面向不变性的架构(immutable architecture)受到更多的关注。人们更多地会在container这一层进行操作,一个纯static link的应用在部署和维护方面将会有天然优势,.so只会增加复杂性。如果单纯从与c等其他语言互操作的角度,似乎用途也不会很广泛(但游戏或ui领域 可能会用到)。不过go 1.5还是增加了对动态链接库的支持,不过从go tool compile和link的doc说明来看,目前似乎还处于实验阶段。

既然go 1.5已经支持了shared library,我们就来实验一下。我们先规划一下测试repository的目录结构:

$GOPATH
    /src
        /testsharedlib
            /shlib
                – lib.go
        /app
            /main.go

lib.go中的代码很简单:

//lib.go
package shlib

import "fmt"

// export Method1
func Method1() {
    fmt.Println("shlib -Method1")
}

对于希望导出的方法,采用export标记。

我们来将这个lib.go编译成shared lib,注意目前似乎只有linux平台支持编译go shared library:

$ go build -buildmode=shared testsharedlib/shlib
# /tmp/go-build709704006/libtestsharedlib-shlib.so
warning: unable to find runtime/cgo.a

编译ok,那个warning是何含义不是很理解。

要想.so被其他go程序使用,需要将.so安装到相关目录下。我们install一下试试:

$ go install -buildmode=shared testsharedlib/shlib
multiple roots /home1/tonybai/test/go/go15/pkg/linux_amd64_dynlink & /home1/tonybai/.bin/go15beta1/go/pkg/linux_amd64_dynlink

go工具居然纠结了,不知道选择放在哪里,一个是$GOPATH/pkg/linux_amd64_dynlink,另外一个则是$GOROOT/pkg/linux_amd64_dynlink,我不清楚这是不是一个bug。

在Google了之后,我尝试了网上的一个解决方法,先编译出runtime的动态共享库:

$go install -buildmode=shared runtime sync/atomic

编译安装后,你就会在$GOROOT/pkg下面看到多出来一个目录:linux_amd64_dynlink。这个目录下的结构如下:

$ ls -R
.:
libruntime,sync-atomic.so  runtime  runtime.a  runtime.shlibname  sync

./runtime:
cgo.a  cgo.shlibname

./sync:
atomic.a  atomic.shlibname

这里看到了之前warning提到的runtime/cgo.a,我们再来重新执行一下build,看看能不能消除warning:

$ go build -buildmode=shared testsharedlib/shlib
# /tmp/go-build086398801/libtestsharedlib-shlib.so
/home1/tonybai/.bin/go15beta1/go/pkg/tool/linux_amd64/link: cannot implicitly include runtime/cgo in a shared library

这回连warnning都没有了,直接是一个error。这里提示:无法在一个共享库中隐式包含runtime/cgo。也就是说我们在构建 testshared/shlib这个动态共享库时,还需要显式的link到runtime/cgo,这里就需要另外一个命令行标志:- linkshared。我们再来试试:

$ go build  -linkshared -buildmode=shared testsharedlib/shlib

这回build成功!我们再来试试install:

$ go install  -linkshared -buildmode=shared testsharedlib/shlib

同样成功了。并且我们在$GOPATH/pkg/linux_amd64_dynlink下发现了共享库:

$ ls -R
.:
libtestsharedlib-shlib.so  testsharedlib

./testsharedlib:
shlib.a  shlib.shlibname

$ ldd libtestsharedlib-shlib.so
    linux-vdso.so.1 =>  (0x00007fff93983000)
    libruntime,sync-atomic.so => /home1/tonybai/.bin/go15beta1/go/pkg/linux_amd64_dynlink/libruntime,sync-atomic.so (0x00007fa150f1b000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa150b3f000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa150921000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fa1517a7000)

好了,既然共享库编译出来了。我们就来用一下这个共享库。

//app/main.go

package main

import (
    "testsharedlib/shlib"
)

func main() {
    shlib.Method1()
}

$ go build -linkshared main.go
$ ldd main
    linux-vdso.so.1 =>  (0x00007fff579f7000)
    libruntime,sync-atomic.so => /home1/tonybai/.bin/go15beta1/go/pkg/linux_amd64_dynlink/libruntime,sync-atomic.so (0x00007fa8d6df2000)
    libtestsharedlib-shlib.so => /home1/tonybai/test/go/go15/pkg/linux_amd64_dynlink/libtestsharedlib-shlib.so (0x00007fa8d6962000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa8d6586000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa8d6369000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fa8d71ef000)

$ main
shlib -Method1

编译执行ok。从输出结果来看,我们可以清晰看到main依赖的.so以及so的路径。我们再来试试,如果将testsharedlib源码目录移除后,是否还能编译ok:

$ go build -linkshared main.go
main.go:4:2: cannot find package "testsharedlib/shlib" in any of:
    /home1/tonybai/.bin/go15beta1/go/src/testsharedlib/shlib (from $GOROOT)
    /home1/tonybai/test/go/go15/src/testsharedlib/shlib (from $GOPATH)

go编译器无法找到shlib,也就说即便是动态链接,我们也要有动态共享库的源码,应用才能编译通过。

internal package

internal包不是go 1.5的原创,在go 1.4中就已经提出对internal package的支持了。但go 1.4发布时,internal package只能用于GOROOT下的go core核心包,用户层面GOPATH不支持internal package。按原计划,go 1.5中会将internal包机制工作范围全面扩大到所有repository的。我原以为1.5beta1以及将internal package机制生效了,但实际结果呢,我们来看看示例代码:

测试目录结构如下:

testinternal/src
    mypkg/
        /internal
            /foo
                foo.go
        /pkg1
            main.go

    otherpkg/
            main.go

按照internal包的原理,预期mypkg/pkg1下的代码是可以import "mypkg/internal/foo"的,otherpkg/下的代码是不能import "mypkg/internal/foo"的。

//foo.go
package foo

import "fmt"

func Foo() {
    fmt.Println("mypkg/internal/foo")
}

//main.go
package main

import "mypkg/internal/foo"

func main() {
    foo.Foo()
}

在pkg1和otherpkg下分别run main.go:

mypkg/pkg1$ go run main.go
mypkg/internal/foo

otherpkg$ go run main.go
mypkg/internal/foo

可以看到在otherpkg下执行时,并没有任何build error出现。看来internal机制并未生效。

我们再来试试import $GOROOT下某些internal包,看看是否可以成功:

package main

import (
    "fmt"
    "image/internal/imageutil"
)

func main() {
    fmt.Println(imageutil.DrawYCbCr)
}

我们run这个代码:

$go run main.go
0x6b7f0

同样没有出现任何error。

不是很清楚为何在1.5beta1中internal依旧无效。难道非要等最终1.5 release版么?

【Vendor】
Vendor机制是go team为了解决go第三方包依赖和管理而引入的实验性技术。你执行以下go env:

$go env
GOARCH="amd64"
GOBIN="/Users/tony/.bin/go15beta1/go/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/tony/Test/GoToolsProjects"
GORACE=""
GOROOT="/Users/tony/.bin/go15beta1/go"
GOTOOLDIR="/Users/tony/.bin/go15beta1/go/pkg/tool/darwin_amd64"
GO15VENDOREXPERIMENT=""
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"

从结果中你会看到新增一个GO15VENDOREXPERIMENT变量,这个就是用来控制vendor机制是否开启的环境变量,默认不开启。若要开启,可以在环境变量文件中设置或export GO15VENDOREXPERIMENT=1临时设置。

vendor机制是在go 1.5beta1发布前不长时间临时决定加入到go 1.5中的,Russ Cox在Keith Rarick之前的一个Proposal的基础上重新做了设计而成,大致机制内容:

If there is a source directory d/vendor, then,
    when compiling a source file within the subtree rooted at d,
    import "p" is interpreted as import "d/vendor/p" if that exists.

    When there are multiple possible resolutions,
    the most specific (longest) path wins.

    The short form must always be used: no import path can
    contain “/vendor/” explicitly.

    Import comments are ignored in vendored packages.

下面我们来测试一下这个机制。首先我们临时开启vendor机制,export GO15VENDOREXPERIMENT=1,我们的测试目录规划如下:

testvendor
    vendor/
        tonybai.com/
            foolib/
                foo.go
    main/
        main.go

$GOPATH/src/tonybai.com/foolib/foo.go

//vendor/tonybai.com/foolib/foo.go
package foo

import "fmt"

func Hello() {
    fmt.Println("foo in vendor")
}

//$GOPATH/src/tonybai.com/foolib/foo.go
package foo

import "fmt"

func Hello() {
    fmt.Println("foo in gopath")
}

vendor和gopath下的foo.go稍有不同,主要在输出内容上,以方便后续区分。

现在我们编译执行main.go

//main/main.go
package main

import (
    "tonybai.com/foolib"
)

func main() {
    foo.Hello()
}

$go run main.go
foo in gopath

显然结果与预期不符,我们通过go list -json来看main.go的依赖包路径:

$go list -json
{
… …
    "Imports": [
        "tonybai.com/foolib"
    ],
    "Deps": [
        "errors",
        "fmt",
        "io",
        "math",
        "os",
        "reflect",
        "runtime",
        "strconv",
        "sync",
        "sync/atomic",
        "syscall",
        "time",
        "tonybai.com/foolib",
        "unicode/utf8",
        "unsafe"
    ]
}

可以看出并没有看到vendor路径,main.go import的是$GOPATH下的foo。难道是go 1.5beta1的Bug?于是翻看各种资料,最后在go 1.5beta1发布前最后提交的revison的commit log中得到了帮助:

cmd/go: disable vendoredImportPath for code outside $GOPATH
It was crashing.
This fixes the build for
GO15VENDOREXPERIMENT=1 go test -short runtime

Fixes #11416.

Change-Id: I74a9114cdd8ebafcc9d2a6f40bf500db19c6e825
Reviewed-on: https://go-review.googlesource.com/11964
Reviewed-by: Russ Cox <rsc@golang.org>

从commit log来看,大致意思是$GOPATH之外的代码的vendor机制被disable了(因为某个bug)。也就是说只有$GOPATH路径下的包在 import时才会考虑vendor路径,我们的代码的确没有在$GOPATH下,我们重新设置一下$GOPATH。

$export GOPATH=~/test/go/go15
[tony@TonydeMacBook-Air-2 ~/test/go/go15/src/testvendor/main]$go list -json
{
  
  … …
    "Imports": [
        "testvendor/vendor/tonybai.com/foolib"
    ],
    "Deps": [
        "errors",
        "fmt",
        "io",
        "math",
        "os",
        "reflect",
        "runtime",
        "strconv",
        "sync",
        "sync/atomic",
        "syscall",
        "testvendor/vendor/tonybai.com/foolib",
        "time",
        "unicode/utf8",
        "unsafe"
    ]
}

这回可以看到vendor机制生效了。执行main.go:

$go run main.go
foo in vendor

这回与预期结果就相符了。

前面提到,关闭GOPATH外的vendor机制是因为一个bug,相信go 1.5正式版发布时,这块会被enable的。

三、小结

Go 1.5还增加了很多工具,如trace,但因文档不全,尚不知如何使用。

Go 1.5标准库也有很多小的变化,这个只有到使用时才能具体深入了解。

Go 1.5更多是Go语言骨子里的变化,也就是runtime和编译器重写。语法由于兼容Go 1,所以基本frozen,因此从外在看来,基本没啥变动了。

至于Go 1.5的性能,官方的说法是,有的程序用1.5编译后会变得慢点,有的会快些。官方bench的结果是总体比1.4快上一些。但Go 1.5在性能方面主要是为了减少gc延迟,后续版本才会在性能上做进一步优化,优化空间还较大的,这次runtime、编译器由c变go,很多地方的go 代码并非是最优的,多是自动翻译,相信经过Go team的优化后,更idiomatic的Go code会让Go整体性能更为优异。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



Statcounter View My Stats