golang 简介

sheepbao 发表了文章 • 0 个评论 • 118 次浏览 • 19 小时前 • 来自相关话题

golang 简介

by sheepbao

主要大概介绍go语言的历史和特性,简单的入门。

来历

很久以前,有一个IT公司,这公司有个传统,允许员工拥有20%自... 查看全部

golang 简介


by sheepbao


主要大概介绍go语言的历史和特性,简单的入门。


来历


很久以前,有一个IT公司,这公司有个传统,允许员工拥有20%自由时间来开发实验性项目。在2007的某一天,公司的几个大牛,正在用c++开发一些比较繁琐但是核心的工作,主要包括庞大的分布式集群,大牛觉得很闹心,后来c++委员会来他们公司演讲,说c++将要添加大概35种新特性。这几个大牛的其中一个人,名为:Rob Pike,听后心中一万个xxx飘过,“c++特性还不够多吗?简化c++应该更有成就感吧”。于是乎,Rob Pike和其他几个大牛讨论了一下,怎么解决这个问题,过了一会,Rob Pike说要不我们自己搞个语言吧,名字叫“go”,非常简短,容易拼写。其他几位大牛就说好啊,然后他们找了块白板,在上面写下希望能有哪些功能(详见问尾)。接下来的时间里,大牛们开心的讨论设计这门语言的特性,经过漫长的岁月,他们决定,以c语言为原型,以及借鉴其他语言的一些特性,来解放程序员,解放自己,然后在2009年,go语言诞生。


思想


Less can be more
大道至简,小而蕴真
让事情变得复杂很容易,让事情变得简单才难
深刻的工程文化


优点



  1. 自带gc。

  2. 静态编译,编译好后,扔服务器直接运行。

  3. 简单的思想,没有继承,多态,类等。

  4. 丰富的库和详细的开发文档。

  5. 语法层支持并发,和拥有同步并发的channel类型,使并发开发变得非常方便。

  6. 简洁的语法,提高开发效率,同时提高代码的阅读性和可维护性。

  7. 超级简单的交叉编译,仅需更改环境变量。(花了我两天时间编译一个imagemagick到arm平台)

  8. 内含完善、全面的软件工程工具。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接口)


    type hen struct {
weight int
hasFeather bool
}

func (h hen)fly(){
fmt.Println("iI can fly")
}

type func (h hen)eat(){
h.weight++
fmt.Println("yes, I can eat")
}

声明一个pig对象(未实现bird接口,因为pig不会fly)


    type pig struct {
age int
weignt int
hasFeather bool
}

func (p pig)run(){
fmt.Println("I can run")
}

func (p pig)eat(){
p.weight += 100
fmt.Println("Yes, I can eat so much")
}

func (p pig)sleep(){
fmt.Println("I slept all my life")
}

// pig can't fly

channel


通道:轻量集队列,传递某种类型的值的通道


    var ch chan int
ch=make(chan int,1)

往ch写入一个数据


    ch<-8888

从ch读取数据


    out:=<-ch

特性:
channel是有长度的,当channel的缓冲为满时,再往里写入就会阻塞,当channel的缓冲为空时,从channel读就会阻塞


package main

import (
"fmt"
"time"
)

func main() {
ch := make(chan int)
fmt.Println("ch len:", len(ch))
go func() {
// 往缓冲满的channel里写数据(阻塞)
// ch <- 1
// 从缓冲为空的channel里读数据(阻塞)
<-ch
fmt.Println("I am in minor goroutine")
}()
fmt.Println("I am in main goroutine")
time.Sleep(2 * time.Second)
}

当长度为0是,就是不带缓冲的channel
长度大于0,就是带缓冲的channel


并发


关键字:go 启动go程
一个普通的函数或方法调用前加上关键字go,即可启动一个goroutine


    go func(){
fmt.Println("start func")
time.Sleep(120*time.Second)
}()

竞争条件检测
-race
race.go


package main

import (
"fmt"
"time"
)

func main() {
a := 1
go func() {
a = 2
}()
a = 3
fmt.Println("a is ", a)

time.Sleep(2 * time.Second)
}

检测:执行go run -race race.go


a is  3
==================
WARNING: DATA RACE
Write at 0x00c420072188 by goroutine 6:
main.main.func1()
/Users/bao/program/go/gowork/hello/src/research/race.go:11 +0x3b

Previous write at 0x00c420072188 by main goroutine:
main.main()
/Users/bao/program/go/gowork/hello/src/research/race.go:13 +0x9f

Goroutine 6 (running) created at:
main.main()
/Users/bao/program/go/gowork/hello/src/research/race.go:12 +0x8e
==================
Found 1 data race(s)

结果分析:
goroutine6运行到第11行和main goroutine运行到13行的时候触发竞争了。而且goroutine6是在第12行的时候产生的。


package


包的管理,关键字importGOPATH


gopath


gopath是一个路径列表,存放go项目工程
GOPATH文件目录结构


├── bin  二进制文件目录
├── pkg 编译好的库文件目录
└── src 源码目录

平常项目的目录结构


├── bin  二进制文件目录
├── pkg 编译好的库文件目录
└── src 源码目录
├── main 入口函数目录
└── vendor 当前项目的库目录
└── sheepbao.com
└── glog

import


比如上面的项目,我要在main.go引入glog


package main

// 引入glog包
import "sheepbao.com/glog"

func main(){
glog.Println("test")
}

go的工程工具简介


test


go的命令工具 test,用来做测试


单元测试


go test
只测试函数名被它正确匹配的测试函数
go test -v -run="French|Canal"


栗子:
add.go


package test

func addOne(i int) int {
return i + 1
}

add_test.go


package test

import "testing"

func TestAddOne(t *testing.T) {
result := addOne(1)
if result != 2 {
t.Error("1+1!=2")
}
}

bao@baoMac test$ go test -v .
=== RUN TestAddOne
--- PASS: TestAddOne (0.00s)
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/test 0.006s

基准测试


go test -bench=.
内存的分配情况
go test -bench=FuncName -benchmem
栗子:
stringsCon.go


package bench

import (
"fmt"
)

func Sprintf(s1, s2, s3 string) string {
return fmt.Sprintf("%s%s%s", s1, s2, s3)
}

func AddString(s1, s2, s3 string) string {
return s1 + s2 + s3
}

stringCon_test.go


package bench

import "testing"

var (
s1 = "make it run!"
s2 = "make it right!"
s3 = "make it fast!"
)

func BenchmarkSprintf(b *testing.B) {
for i := 0; i < b.N; i++ {
Sprintf(s1, s2, s3)
}
}

func BenchmarkAddString(b *testing.B) {
for i := 0; i < b.N; i++ {
AddString(s1, s2, s3)
}
}

go test -bench=.


bao@baoMac bench$ go test -bench=.
testing: warning: no tests to run
BenchmarkSprintf-4 5000000 349 ns/op
BenchmarkAddString-4 20000000 61.7 ns/op
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/bench 3.414s

样本测试


package et

import (
"fmt"
)

func ExampleHello() {
fmt.Println("hello, sewise")
// Output: hello, sewise
}

bao@baoMac example$ go  test -v .
=== RUN ExampleHello
--- PASS: ExampleHello (0.00s)
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/example 0.006s

如果把上面的// Output: hello, sewise改为// Output: hello, sewis
则样本测试不能通过


bao@baoMac example$ go  test -v .
=== RUN ExampleHello
--- FAIL: ExampleHello (0.00s)
got:
hello, sewise
want:
hello, sewis
FAIL
exit status 1
FAIL _/Users/bao/program/go/gowork/hello/src/research/example 0.006s

pprof


go的命令工具 pprof,用来性能分析(内存使用,泄露和cpu消耗)
go tool pprof



可视化(原是svg文件,下图为截图):


image_1b72f233avto14d7on4h3nlm51g.png-129.8kB



可视化(原是svg文件,下图为截图:


image_1b72euk7b1knr1d1n1ugq2pe19kim.png-176.7kB


go tool pprof --text http://localhost:6060/debug/pprof/heap


go命令教程


资料


http://www.csdn.net/article/2012-07-04/2807113-less-is-exponentially-more


http://www.jianshu.com/p/91e40c3e3acb?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io


http://smallsoho.com/2016/11/20/Go简明教程.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io


大牛真身


最大牌的当属B和C语言设计者、Unix和Plan 9创始人、1983年图灵奖获得者Ken Thompson,这份名单中还包括了Unix核心成员Rob Pike(go语言之父)、java HotSpot虚拟机和js v8引擎的开发者Robert Griesemer、Memcached作者Brad Fitzpatrick,等等。


功能



  • 规范的语法(不需要符号表来解析)

  • 垃圾回收(独有)

  • 无头文件

  • 明确的依赖

  • 无循环依赖

  • 常量只能是数字

  • int和int32是两种类型

  • 字母大小写设置可见性(letter case sets visibility)

  • 任何类型(type)都有方法(不是类型)

  • 没有子类型继承(不是子类)

  • 包级别初始化以及明确的初始化顺序

  • 文件被编译到一个包里

  • 包package-level globals presented in any order

  • 没有数值类型转换(常量起辅助作用)

  • 接口隐式实现(没有“implement”声明)

  • 嵌入(不会提升到超类)

  • 方法按照函数声明(没有特别的位置要求)

  • 方法即函数

  • 接口只有方法(没有数据)

  • 方法通过名字匹配(而非类型)

  • 没有构造函数和析构函数

  • postincrement(如++i)是状态,不是表达式

  • 没有preincrement(i++)和predecrement

  • 赋值不是表达式

  • 明确赋值和函数调用中的计算顺序(没有“sequence point”)

  • 没有指针运算

  • 内存一直以零值初始化

  • 局部变量取值合法

  • 方法中没有“this”

  • 分段的堆栈

  • 没有静态和其它类型的注释

  • 没有模板

  • 内建string、slice和map

  • 数组边界检查

2017年 GopherChina 大会期望在哪里召开?

go、go、go 回复了问题 • 17 人关注 • 19 个回复 • 691 次浏览 • 22 小时前 • 来自相关话题

GopherChina 2017年讲师招募

astaxie 发表了文章 • 7 个评论 • 244 次浏览 • 2017-01-12 14:24 • 来自相关话题

会议详情: 时间:2017年4月15-16日 地点:上海

GopherChina 是中国的最权威和最实力干货的Go大会,我们致力于为中国广大的Gopher提供最好的大会,我们本着非盈利目的来举办大会,前面两届大会在上海和北京都获得了非常好的... 查看全部

会议详情:
时间:2017年4月15-16日
地点:上海


GopherChina 是中国的最权威和最实力干货的Go大会,我们致力于为中国广大的Gopher提供最好的大会,我们本着非盈利目的来举办大会,前面两届大会在上海和北京都获得了非常好的口碑,今年我们大会将在四月份举办大会。举办Gopher大会,主要是汇集Gopher的广大开发者,聚集一批大规模应用Go的示范企业给大家分享,呈现一场cool的盛会。


这是2015年Go作者之一Robert参会之后写的博客:https://blog.golang.org/gopherchina


第一届我们的大会参会人数是500人,去年在北京差不多达到了1000人的规模, 今年我们组织了1500人的场地,面向的受众也是越来越多,同时我们也邀请了Go team的同学过来分享。


现在开始招募讲师:


https://jinshuju.net/forms/kFEn6i

golang读取java或者go的webservice服务

小蚂蚁 发表了文章 • 0 个评论 • 106 次浏览 • 2017-01-06 19:21 • 来自相关话题

原来结构体函数还能这样用

myml 发表了文章 • 5 个评论 • 214 次浏览 • 2017-01-06 11:04 • 来自相关话题

平常使用结构体函数是这么用

type A struct {
}

func (a *A) Print() {
    fmt.... 			查看全部
					

平常使用结构体函数是这么用


type A struct {
}

func (a *A) Print() {
fmt.Println("this is A")
}

func main() {
a := A{}
a.Print()
}

恩,没啥问题,然后还可以这样用


type A struct {
}

func (a A) Print() {
fmt.Println("this is A")
}
func (a *A) Print2() {
fmt.Println("this is A")
}

func main() {
a := A{}
A.Print(a)
(*A).Print2(&a)
}

结合接口的话就可以这样


type I interface {
Print()
}
type A struct {
}

func (a *A) Print() {
fmt.Println("this is A")
}

type B struct {
}

func (b *B) Print() {
fmt.Println("this is B")
}

func main() {
a := A{}
b := B{}
I.Print(&a)
I.Print(&b)
}

谷歌开源了一个从 Python 到 Go 的编译器 grumpy

回复

cholerae 发起了问题 • 1 人关注 • 0 个回复 • 333 次浏览 • 2017-01-05 12:21 • 来自相关话题

Go语言单元测试

oscarzhaosl 发表了文章 • 2 个评论 • 299 次浏览 • 2016-12-29 01:46 • 来自相关话题

简介

Go 语言在设计之初就考虑到了代码的可测试性。一方面 Go 本身提供了 testing 库,使用方法很简单... 查看全部

简介


Go 语言在设计之初就考虑到了代码的可测试性。一方面 Go 本身提供了 testing 库,使用方法很简单;
另一方面 go 的 package 提供了很多编译选项,代码和业务逻辑代码很容易解耦,可读性比较强(不妨对比一下C++测试框架)。 本文中,我们讨论的重点是 Go 语言中
的单元测试,而且只讨论一些基本的测试方法,包括下面几个方面:



  1. 写一个简单的测试用例

  2. Table driven test

  3. 使用辅助测试函数(test helper)

  4. 临时文件


这里我们只涉及到一些通用的测试方法。关于 HTTP server/client 测试,这里不做深入讨论。


阅读建议


Testing shows the presence, not the absence of bugs -- Edsger W. Dijkstra


在阅读本文之前,建议您对 Go 语言的 package 有一定的了解,并在实际项目中使用过,下面是一些基本的要求:



  1. 了解如何在项目中 import 一个外部的package

  2. 了解如何将自己的项目按照功能模块划分 package

  3. 了解 struct、struct字段、函数、变量名字首字母大小写的含义(非必需)

  4. 了解一些 Go语言的编译选项,比如 +build !windows(非必需)


如果你对 1、2都不太了解,建议阅读一下这篇文章How to Write Go Code,动手实践一下。


写一个简单的测试用例


为了便于理解,我们首先给出一个代码片段(如果你已经使用过go 的单元测试,可以跳过这个环节):


// demo/equal.go
package demo

// a function to check if two numbers equals to each other.
func equal(a, b int) bool {
return a == b
}

// demo/equal_test.go
package demo
import (
"testing"
)

func TestEqual(t *testing.T) {
a := 1
b := 1
shouldBe := true
if real := equal(a, b); real == shouldBe {
t.Errorf("equal(%d, %d) should be %v, but is:%v\n", a, b, shouldBe, real)
}
}

上面这个例子中,如果你从来没有使用过单元测试,建议在本地开发环境中运行一次。这里有几点需要注意一下:



  1. 这两个文件的父目录必须与包名一致(这里是 demo),且包名必须是在 $GOPATH 下

  2. 测试用例的函数命名必须符合 TestXXX 格式,并且参数是 t *testing.T

  3. 了解一下 t.Errorf 与 t.Fatalf 的行为差异


Table Driven Test


上面的测试用例中,我们一次只能测试一种情况,如果我们希望在一个 TestXXX 函数中进行很多项测试,Table Driven Test 就派上了用场。
举个例子,假设我们实现了自己的 Sqrt 函数 mymath.Sqrt,我们需要对其进行测试:


首先,我们需要考虑一些特殊情况:



  1. Sqrt(+Inf) = +Inf

  2. Sqrt(±0) = ±0

  3. Sqrt(x < 0) = NaN

  4. Sqrt(NaN) = NaN


然后,我们需要考虑一般情况:



  1. Sqrt(1.0) = 1.0

  2. Sqrt(4.0) = 2.0

  3. ...


注意:在一般情况中,我们对结果进行验证时,需要考虑小数点精确位数的问题。由于文章篇幅限制,这里不做额外的处理。


有了思路以后,我们可以基于 Table Driven Test 实现测试用例:


func TestSqrt(t *testing.T) {
var shouldSuccess = []struct {
input float64 // input
expected float64 // expected result
}{
{math.Inf(1), math.Inf(1)}, // positive infinity
{math.Inf(-1), math.NaN()}, // negative infinity
{-1.0, math.NaN()},
{0.0, 0.0},
{-0.0, -0.0},
{1.0, 1.0},
{4.0, 2.0},
}
for _, ts := range shouldSuccess {
if actual := Sqrt(t.input); actual != ts.expected {
t.Fatalf("Sqrt(%f) should be %v, but is:%v\n", ts.input, ts.expected, actual)
}
}
}

辅助函数 (test helper)


在写测试的过程中,我们可能遇到下面几个场景:



  1. 待测试的功能需要一些前提条件,比如初始化数据库连接、打开文件、创建资源

  2. 核心功能测试结束后,需要一些清理工作,比如关闭文件、销毁资源

  3. 待测试的功能错误分类比较多,考虑到table driven test,写到一个测试函数里可读性比较差


这时候,我们需要定义一些辅助函数,以协助核心功能的测试。下面我们以用户登录校验为例,来看如何使用辅助函数。
我们要测试的函数是 login,为了保证本次单元测试不会污染数据库,我们采取的流程是:



  1. 初始化数据库连接(类似于 Junit 中的 @Before)

  2. 创建一个用户 (类似于 Junit 中的 @Before)

  3. 测试 login

  4. 删除该用户(类似于 Junit 中的 @After)


确定了测试的逻辑以后,我们看下代码:


// file name: user_test.go
// source code: https://github.com/oscarzhao/b ... st.go

// package level initialization of database connections
func init() {
// init database connections
}

// testCreateUser 创建一个临时用户(test helper)
// 具体流程:
// 1. mocks a http server
// 2. send create user request to the server
func testCreateUser(t *testing, userSpec map[string]string) (int, []byte) {
// mock a http server
router := denco.New()
router.Build([]denco.Record{
{"/api/v1/users/:user_id", &route{}},
})

testURL := "/api/v1/users/" + userID
_, params, found := router.Lookup(testURL)
if !found {
t.Fatalf("fails to look up the route, url:%s\n", testURL)
}

handler := func(w http.ResponseWriter, r *http.Request) {
CreateUser(w, r, params)
}

marshaled, _ := json.Marshal(userSpec)
// create request
req, err := http.NewRequest("POST", "http://anything.com", bytes.NewBuffer(marshaled))
if err != nil {
t.Fatalf("should create user success, but fails to send request, error:%s\n", err)
}

// mock ResponseWriter
w := httptest.NewRecorder()
// call create operation
handler(w, req)
return w.Code, w.Body.Bytes()
}

// testDeleteUser 根据 userID 删除一个用户(test helper)
func testDeleteUser(t *testing.T, userID string) (int, []byte) {
...
}

// TestVerifyLogin 创建用户、测试登录,然后删除该用户
// 该函数由 go 语言的 test 框架调用
func TestVerifyLogin(t *testing.T) {
userID := uuid.NewV4().String()
data := map[string]string{
"username": "simple_yyxxzz",
"password": "simple_password",
"email": "not@changed.com",
"phone": "1234567890",
}
statusCode, msg := testCreateUser(t, userID, data)
if statusCode >= http.StatusBadRequest {
t.Fatalf("should succeeed, create user (%s), but fails, error:%s\n", userID, msg)
}
// 测试结束时,清理数据
defer func(userID string) {
statusCode, msg := testDeleteUser(t, userID)
if statusCode >= http.StatusBadRequest {
t.Errorf("should delete user(%s) successfully, but fails, status code:%d, error:%s\n", userID, statusCode, msg)
}
}(userID)

// 测试登录功能
shouldSuccess := xxx
for _, ts := range shouldSuccess {
statusCode, msg = testVerifyPassword(t, ts)
if statusCode != http.StatusOK {
// if use fatal, user will not be cleaned up
t.Errorf("should verify with %v successfully, but failed, status code:%d, error:%s\n", ts, statusCode, msg)
return
}
}
}

在测试代码中,我们推荐使用 t.Fatalf , 而不是 t.Errorf,一方面测试代码不需要做太多容错,另一方面增加了测试代码的可读性。


临时文件


如果待测试的功能模块涉及到文件操作,临时文件是一个不错的解决方案。go语言的 ioutil 包提供了 TempDir 和
TempFile 方法,供我们使用。


我们以 etcd 创建 wal 文件为例,来看一下 TempDir 的用法:


// github.com/coreos/etcd/wal/wal_test.go

func TestNew(t *testing.T) {
p, err := ioutil.TempDir(os.TempDir(), "waltest")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(p) // 千万不要忘记删除目录

w, err := Create(p, []byte("somedata"))
if err != nil {
t.Fatalf("err = %v, want nil", err)
}
if g := path.Base(w.tail().Name()); g != walName(0, 0) {
t.Errorf("name = %+v, want %+v", g, walName(0, 0))
}
defer w.Close()

// 将文件 waltest 中的数据读取到变量 gb []byte 中
// ...

// 根据 "somedata" 生成数据,存储在变量 wb byte.Buffer 中
// ...

// 临时文件中的数据(gb)与 生成的数据(wb)进行对比
if !bytes.Equal(gd, wb.Bytes()) {
t.Errorf("data = %v, want %v", gd, wb.Bytes())
}
}

上面这段代码是从 etcd 中摘取出来的,源码查看 coreos/etcd - Github
需要注意的是,使用 TempDirTempFile 创建文件以后,需要自己去删除。


关于 package


在写单元测试时,一般情况下,我们将功能代码和测试代码放到同一个目录下,仅以后缀 _test 进行区分。


对于复杂的大型项目,功能依赖比较多时,通常在跟目录下再增加一个 test 文件夹,不同的测试
放到不同的子目录下面,如下图所示:


kubernetes/kubernetes


针对自己的项目进行测试时,可以结合这两种方式实现测试用例,提高代码的可读性和可维护性。


相关链接:



  1. golang.org/pkg/testing

  2. [Testing Techniques](https://talks.golang.org/2014/testing.slide “testing techniques")

  3. Table Driven Test

  4. Learn Testing


扫码关注微信公众号“深入Go语言”


在这里

Gitea 1.0 发布了,Go语言开发的自助 Git 服务

lunny 发表了文章 • 3 个评论 • 567 次浏览 • 2016-12-25 13:36 • 来自相关话题

今天我们很高兴的宣布 Gitea 1.0.0 发布了。在这个版本我们解决了 查看全部

今天我们很高兴的宣布 Gitea 1.0.0 发布了。在这个版本我们解决了 44 个问题,合并了 238 次提交请求。二进制下载请访问 下载页面,根据您的操作系统和架构进行选择,进一步的安装信息请访问 安装文档。如果您是从Gogs升级的请访问 从Gogs迁移。更多信息请访问官网https://gitea.io 和 github https://github.com/go-gitea


变更日志



  • BREAKING

    • We have various changes on the API, scripting against API must be updated


  • FEATURE

    • Show last login for admins #121


  • BUGFIXES

    • Fixed sender of notifications #2

    • Fixed keyword hijacking vulnerability #20

    • Fixed non-markdown readme rendering #95

    • Allow updating draft releases #169

    • GitHub API compliance #227

    • Added commit SHA to tag webhook #286

    • Secured links via noopener #315

    • Replace tabs with spaces on wiki title #371

    • Fixed vulnerability on labels and releases #409

    • Fixed issue comment API #449


  • ENHANCEMENT

    • Use proper import path for libravatar #3

    • Integrated DroneCI for tests and builds #24

    • Integrated dependency manager #29

    • Embedded bindata optionally #30

    • Integrated pagination for releases #73

    • Autogenerate version on every build #91

    • Refactored Docker container #104

    • Added short-hash support for downloads #211

    • Display tooltip for downloads #221

    • Improved HTTP headers for issue attachments #270

    • Integrate public as bindata optionally #293

    • Integrate templates as bindata optionally #314

    • Inject more ENV variables into custom hooks #316

    • Correct LDAP login validation #342

    • Integrate conf as bindata optionally #354

    • Serve video files in browser #418

    • Configurable SSH host binding #431


  • MISC

    • Forked from Gogs and renamed to Gitea

    • Catching more errors with logs

    • Fixed all linting errors

    • Made the go linter entirely happy

    • Really integrated vendoring


Machine Learning with go

回复

songtianyi 发起了问题 • 2 人关注 • 0 个回复 • 247 次浏览 • 2016-12-23 13:44 • 来自相关话题

通过 github.com/jung-kurt/gofpdf 包实现自定义字体库的添加及PDF的生成

xieyanke 发表了文章 • 0 个评论 • 183 次浏览 • 2016-12-22 23:05 • 来自相关话题

为朋友做个demo,顺便分享一下:

github.com/jung-kurt/gofpdf 是一个用于生成PDF的包

包的安装及自定义字库添加工具的安装

  1. go get github.com/jun... 查看全部

为朋友做个demo,顺便分享一下:


github.com/jung-kurt/gofpdf 是一个用于生成PDF的包


包的安装及自定义字库添加工具的安装



  1. go get github.com/jung-kurt/gofpdf

  2. go install github.com/jung-kurt/gofpdf/makefont


通过 makefont 工具生成自定义字体库



  1. makefont -dst=fonts -embed -enc=/Users/xieyanke/GOPATH/src/github.com/jung-kurt/gofpdf/font/cp1252.map /Library/Fonts/Chalkduster.ttf


这里 makefont -dst 指定了相对路径 fonts 这个目录作为字库生成的目录,后面代码中加载字库需要引用这个路径


package main

import (
"log"

"github.com/jung-kurt/gofpdf"
)

func main() {
// 这里./fonts 是指定了makefont 工具生成自定义字体库的目录
pdf := gofpdf.New("P", "mm", "A4", "./fonts")
// 加载定义的字库
pdf.AddFont("cld", "", "Chalkduster.json")
pdf.AddPage()
pdf.SetFont("cld", "", 22)
pdf.Cell(40, 10, "A new pdf")

err := pdf.OutputFileAndClose("demo.pdf")

if err != nil {
log.Println(err)
}
}
// go run example.go,查看当前目录下 pdf 进行验证

Docker 1.13最实用命令行:终于可以愉快地打扫房间了

数人云 发表了文章 • 0 个评论 • 210 次浏览 • 2016-12-22 11:09 • 来自相关话题

Docker 1.13出来已经有一段时间了,新版本添加了许多有用的命令,本文作者从处女座的洁癖(此处有雾)出发,告诉大家一些整理环境的小技巧。打扫房间... 查看全部


Docker 1.13出来已经有一段时间了,新版本添加了许多有用的命令,本文作者从处女座的洁癖(此处有雾)出发,告诉大家一些整理环境的小技巧。打扫房间再也不需费时又费力了,简单的命令,就可以轻松地把物品分门别类(容器、镜像、网络、存储卷……)地整理好^_^



在1.13版本中,Docker向CLI添加了一些有用的命令,让环境更加整洁。你可能已经体验了很长时间乱糟糟的开发环境——无用的容器,挂起的Docker镜像,弃置的volume,被遗忘的网络……所有这些过时的事物占据了宝贵的资源,最终导致环境无法使用。在之前的文章中曾经提到用各种各样的命令保持环境的整洁,例如:


docker rm -f $(docker ps -aq)


强制地删除所有正在运行的、暂停的以及终止的容器。同样地,也有命令可以删除挂起的镜像、网络和volume。


尽管上述命令解决了问题,但是它们要么专有,要么冗长或者难用。而新加入的命令直截了当又简单好用,现在就开始一一介绍吧。


管理命令


为了整理CLI,Docker 1.13引进了新的管理命令,如下:



  • system

  • container

  • image

  • plugin

  • secret


Docker的老版本中已经有了 network, node, service, swarm 和 volume 。这些新命令组子命令过去作为root命令直接实现。举个例子:


docker exec -it [container-name] [some-command]


exec 命令现在是 container 下面的一个子命令,这个命令相当于:


docker container exec -it [container-name] [some-command]


个人猜测为了兼容性的考虑,旧语句眼下还会使用一段时间。


Docker系统


现在有一个新管理命令 system 。它有4个子命令分别是 df, events, info 和 prune 。命令 docker system df 提供Docker整体磁盘使用率的概况,包括镜像、容器和(本地)volume。所以我们现在随时都可以查看Docker使用了多少资源。


如果之前的命令展示出 docker 已经占用了太多空间,我们会开始清理。有一个包办一切的命令:


docker system prune


这个命令会删除当前没有被使用的一切项目,它按照一种正确的序列进行清理,所以会达到最大化的输出结果。首先删除没有被使用的容器,然后是volume和网络,最后是挂起的镜像。通过使用 y 回复来确认操作。如果想在脚本中使用这个命令,可以使用参数 --force 或者 -f 告诉Docker不要发来确认请求。


Docker容器


我们已经知道许多 docker container 的子命令。它们过去(现在也是)是 docker 的直接子命令。可以通过下面的命令得到完整的子命令列表:


docker container --help


在列表中会看到一个 prune 命令。如果使用它,那么只会删除无用的容器。因此这条命令比 docker system prune 命令更局限。使用 --force 或者 -f 同意可以让CLI不再进行确认请求。


Docker网络


这里也有一个 prune 命令:


docker network prune


删除所有孤立的网络。


Docker Volume


volume也有新的 prune 命令了:


docker volume prune


删除所有(本地)没有被容器使用的volume。


Docker镜像


新的镜像命令也是 prune 子命令。--force 用法如上面一样, --all 可以删除所有不用的镜像,不只挂起的镜像。


docker image prune --force --all


这个命令可以删除所有不使用的镜像并且不再请求确认。


总结


Docker 1.13不仅通过引入admin command添加了一些需要的命令,也让我们找到了一些非常有用的清理环境的命令。笔者最爱的命令莫过于 docker system prune,让环境一直保持干净整齐。


本文作者:Gabriel Schenker
原文链接:https://lostechies.com/gabrielschenker/2016/12/12/containers-cleanup-your-house-revisited/

解读2016之Golang篇:极速提升,逐步成熟

wwdyy 发表了文章 • 9 个评论 • 616 次浏览 • 2016-12-17 14:39 • 来自相关话题

Go语言已经7岁了!今年8月,Go 1.7如期发布。撰写本稿时,Go 1.8的测试版也出来了。我们正在热切盼望着明年2月的Go 1.8正式版。

如果你关注 TIOBE的编程语言排行榜 就会发现,截止到2016年11月,Go语言从原先的第50... 查看全部

Go语言已经7岁了!今年8月,Go 1.7如期发布。撰写本稿时,Go 1.8的测试版也出来了。我们正在热切盼望着明年2月的Go 1.8正式版。


如果你关注 TIOBE的编程语言排行榜 就会发现,截止到2016年11月,Go语言从原先的第50多位经过多次上窜已经跃到了第13位,跻入绝对主流的编程语言的行列!这份排行榜每月都会更新,并基于互联网上的程序员老鸟、教学课程和相关厂商的数量进行排名。在国内,从我这几年运营Go语言北京用户组的经历来看,可以明显地感觉到Go语言的在国内的大热。N多初创互联网企业都选用Go语言作为他们的基础技术栈。我还发现,已经有在大数据、机器人等尖端科技领域耕耘的国内公司开始使用Go语言。这门语言现在已经是无孔不入了。


1. 回顾


遥想去年的1.5版本,Go运行时系统和标准库刚完成去C化,转而完全由Go语言和汇编语言重写。到现在,Go的源码已有了较大的改进,Go语言版本的Go语言也更加成熟了。我下面就带领大家一起回顾一下Go语言在2016年做出的那些大动作。


1.1 极速GC


当然,首先要说的还是性能。Go语言本身最大的性能提升依然在GC(garbage collection,垃圾回收)方面。从Go 1.5时标榜的GC耗时百毫秒级,到今天的全并发GC使得耗时达到毫秒级,再到即将发布的Go 1.8由于实施了诸多改进而达成的百微秒级以下的GC耗时,真可谓是突飞猛进!


图1 GC停顿时间——Go 1.5 vs. Go 1.6



图2 GC停顿时间——Go 1.7


在经历了如此变化之后,如果你现在再说你的Go程序的性能瓶颈在GC上,那只能让人侧目了。


当然,Go语言对自身性能的提升远不止于此。


1.2 对HTTP/2的支持


很早以前,Go语言团队就开始跟进HTTP/2草案了。从Go 1.6开始,我们其实已经可以间接地在Go程序中使用到HTTP/2了,应用场景如:使用Go程序开发基于HTTPS协议的服务端和客户端。不过,这一切都是自动适配的,Go官方并未暴露出可以指定或配置HTTP/2模块的任何API。另外,在还未发布的Go 1.8中,HTTP/2还会得到更广泛的支持。


1.3 httptrace包


Go 1.7的标准库中新增了net/http/httptrace代码包(https://godoc.org/net/http/httptrace)。
它提供了一种调试HTTP请求和响应的方式。你可以像下面这样轻易地获取基于HTTP协议的通讯过程的详细信息。


package main

import (
"context"
"fmt"
"log"
"net/http"
"net/http/httptrace"
"os"
)

func main() {
traceCtx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
GetConn: func(hostPort string) {
fmt.Printf("Prepare to get a connection for %s.\n", hostPort)
},
GotConn: func(info httptrace.GotConnInfo) {
fmt.Printf("Got a connection: reused: %v, from the idle pool: %v.\n",
info.Reused, info.WasIdle)
},
PutIdleConn: func(err error) {
if err == nil {
fmt.Println("Put a connection to the idle pool: ok.")
} else {
fmt.Println("Put a connection to the idle pool:", err.Error())
}
},
ConnectStart: func(network, addr string) {
fmt.Printf("Dialing... (%s:%s).\n", network, addr)
},
ConnectDone: func(network, addr string, err error) {
if err == nil {
fmt.Printf("Dial is done. (%s:%s)\n", network, addr)
} else {
fmt.Printf("Dial is done with error: %s. (%s:%s)\n", err, network, addr)
}
},
WroteRequest: func(info httptrace.WroteRequestInfo) {
if info.Err == nil {
fmt.Println("Wrote a request: ok.")
} else {
fmt.Println("Wrote a request:", info.Err.Error())
}
},
GotFirstResponseByte: func() {
fmt.Println("Got the first response byte.")
},
})
req, err := http.NewRequest("GET", "http://www.golang.org/", nil)
if err != nil {
log.Fatal("Fatal error:", err)
}
req = req.WithContext(traceCtx)
_, err = http.DefaultClient.Do(req)
if err != nil {
fmt.Fprintf(os.Stderr, "Request error: %v\n", err)
os.Exit(1)
}
}

强烈建议你动手运行一下这个小程序,享受一下掌控全局的感觉。


1.4 子测试


Go 1.7中增加了对子测试(https://blog.golang.org/subtests
的支持,包括功能测试和性能测试。子测试的主要目的是在测试函数中区分和展示因不同的测试参数或测试数据带来的不同的测试结果。请看下面的测试程序。


package subtest

import (
"fmt"
"math/rand"
"strconv"
"testing"
)

// KE 代表键-元素对。
type KE struct {
key string
element int
}

// BenchmarkMapPut 用于对字典的添加和修改操作进行测试。
func BenchmarkMapPut(b *testing.B) {
max := 5
var kes []KE
for i := 0; i <= max; i++ {
kes = append(kes, KE{strconv.Itoa(i), rand.Intn(1000000)})
}
m := make(map[string]int)
b.ResetTimer()
for _, ke := range kes {
k, e := ke.key, ke.element
b.Run(fmt.Sprintf("Key: %s, Element: %#v", k, e), func(b *testing.B) {
for i := 0; i < b.N; i++ {
m[k] = e + i
}
})
}
}

在程序所在目录下使用go test -run=^$ -bench .命令运行它之后就会看到,针对每一个子测试,go test命令都会打印出一行测试摘要。它们是分离的、独立统计的。这可以让我们进行更加精细的测试,细到每次输入输出。上述打印内容类似:
BenchmarkMapPut/Key:_0425,_Element:_498081-4 30000000 40.6 ns/op
BenchmarkMapPut/Key:_1540,_Element:_727887-4 30000000 41.7 ns/op
BenchmarkMapPut/Key:_2456,_Element:_131847-4 30000000 43.3 ns/op
BenchmarkMapPut/Key:_3300,_Element:_984059-4 30000000 46.1 ns/op
BenchmarkMapPut/Key:_4694,_Element:_902081-4 30000000 48.4 ns/op
BenchmarkMapPut/Key:_5511,_Element:_941318-4 30000000 59.3 ns/op
PASS


ok _/Users/haolin/infoq-2016_review_go /demo/subtest 8.678s


1.5 vendor目录


在Go 1.5的时候,官方启用了一个新的环境变量——GO15VENDOREXPERIMENT。该环境变量可以启动Go的vendor目录
https://golang.org/s/go15vendor
并用于存放当前代码包依赖的代码包。在Go 1.5中,若GO15VENDOREXPERIMENT的值为1则会启动vendor目录。Go 1.6正相反,默认支持vendor目录,当GO15VENDOREXPERIMENT的值为0时禁用vendor目录。到了Go 1.7,官方完全去掉了这个环境变量。这也代表着对vendor目录的正式支持。Go语言的实验特性一般都是按照类似的路数一步步迈向正式版的。


1.6 其他值得一提的改进


1.6.1 检测并报告对字典的非并发安全访问


从Go 1.6开始,Go运行时系统对字典的非并发安全访问采取零容忍的态度。请看下面的程序。


package main

import "sync"

func main() {
const workers = 100
var wg sync.WaitGroup
wg.Add(workers)
m := map[int]int{}
for i := 1; i <= workers; i++ {
go func(i int) {
for j := 0; j < i; j++ {
m[i]++
}
wg.Done()
}(i)
}
wg.Wait()
}

该程序在未施加任何保护的情况下在多个Goroutine中并发地访问了字典实例m。我们知道,Go原生的字典类型是非并发安全的。所以上面这样做很可能会让m的值产生不可预期的变化。这在并发程序中应该坚决避免。在1.6之前,如此操作的Go程序并不会因此崩溃。但是在1.6,运行上述程序后就立刻会得到程序崩溃的结果。Go运行时系统只要检测到类似代码,就会强制结束程序并报告错误。


1.6.2 sort包的性能提升


Go语言团队一直致力于标准库中众多API的性能提升,并且效果向来显著。我把sort包单拎出来强调是因为sort.Sort函数因性能优化而在行为上稍有调整。在Go 1.6,sort.Sort函数减少了大约10%的比较操作和交换操作的次数,从而获得了20%~50%的性能提升。不过,这里有一个副作用,那就是sort.Sort函数的执行会使排序算法不稳定。所谓不稳定的排序算法,就是排序可能会使排序因子相等的多个元素在顺序上不确定。比如,有如下需要根据长度排序的字符串的切片:


var langs= []string{"golang", "erlang", "java", "python", "php", "c++", "perl"}

经sort.Sort函数排序后,该切片只几个长度相等的元素golang、erlang和python的先后顺序可能就不是这样了,可能会变成erlang、golang、python。虽然它依然会依据排序因子(这里是字符串长度)进行完全正确的排序,但是如此确实可能对一些程序造成影响。


如果你需要稳定的排序,可以使用sort.Stable函数取而代之。


1.6.3 context包进入标准库


在Go 1.7发布时,标准库中已经出现了一个名为context的代码包。该代码包原先的导入路径为golang.org/x/context,而后者现在已经不存在了。context包被正式引入标准库,并且标准库中的很多API都因此而做了改变。context.Context类型的值可以协调多个Groutine中的代码执行“取消”操作,并且可以存储键值对。最重要的是它是并发安全的。与它协作的API都可以由外部控制执行“取消”操作,比如:取消一个HTTP请求的执行。


1.6.4 go tool trace的增强


go tool trace自Go 1.5正式加入以来,成为了Go程序调试的又一利器。到了Go 1.7,它已经得到了大幅增强。比如,执行时间的缩短、跟踪信息的丰富,等等。


1.6.5 unicode包现基于Unicode 9.0


Go 1.7升级了unicode包,使它支持Unicode 9.0标准。在这之前,它支持的Unicode 8.0标准。


1.6.6 新的编译器后端——SSA


SSA 作为新的编译器后端,可以让编译器生成压缩比和执行效率都更高的代码,并为今后的进一步优化提供了更有力的支持。在性能方面,它可以让程序减少5%至35%的CPU使用时间。


到这里,我向大家展示了Go语言在2016年的一些显著变化。由于篇幅原因,还有很多Go运行时系统和标准库的改动没能提及。尤其是性能方面的改进一直在持续,并潜移默化地为广大Go程序员提供着底层红利。


我强烈建议所有Go程序员紧跟Go语言团队的脚步,升级版本,享受红利。


2. 展望


2.1 新版本


关于展望,莫过于广大Go程序员翘首期盼的Go 1.8了。这里提一下几个如甘霖般的特性。


Go编写的HTTP服务器支持平滑地关闭。这一功能早已由很多第三方代码包实现,但是这次官方终于给出了答案。
支持HTTP/2的Server Push。这个就不多说了,肯定会比Hijack更好用。
新增了plugin包,你可以把一些Go程序作为插件动态地加载进你的程序了。
更广泛的上下文支持,自从标准库中有了context包,它就在很多地方起作用了。很多基于标准库的接口功能都可以执行“取消”操作。在Go 1.8中,范围将进一步扩大,比如:database/sql包和testing包都对上下文进行了支持。
sort包的功能改进,对于切片,我们不用再为了使用它的排序功能去编写某个接口的实现类型。
go test命令有了新的标记:-mutexprofile。该标记用于提供关于锁争用的概要文件。
当然,最值得期待的仍然是Go在性能上的提升,尤其是GC方面,又要有一次飞跃了!另外,defer语句的执行会比之前快整整两倍!cgo的调用开销也降低了将近一半!


2.2技术社区


其实,除了对Go语言本身的展望,我们也应该憧憬Go社区(尤其是国内Go社区)的发展。中国现在已经差不多是Go程序员最多的国家了。如果打开Github上Go语言的Wiki(https://github.com/golang/go/wiki/GoUsers
你就会发现,那里已经有一个非常长的列表了。其中的公司达到了近200家,相比于2015年年底翻了将近三倍。而且我相信这只是一小部分,只是在Github上有自己的官方组织且对社区有贡献的一部分公司。不过,你可能还会发现,在China那一栏下的公司却只有一家。这是为什么呢?比较值得深思。我想这也许能从侧面反映出对国际技术社区(尤其是开源社区)有贡献的国内公司太少的问题。在2016年12月初举办的一个大型开源技术盛典的讲台上,某开源公司CEO提到了程序员对开源社区应该不只索取更要奉献,这样才能更好地宣传和推销自己。同时,组织机构也不应该成为大家合作的瓶颈。但是,我想国内的实际情况却恰恰相反。我们国内的计算机技术公司,甚至技术驱动的互联网公司,大都没有为开源社区做奉献的习惯,甚至从规章制度上就是明令禁止的。从这方面看,我觉得那个列表中的China栏的惨状也着实不冤。我热切盼望到了明年这个China栏能够变长很多。


不过,从Github以及国内一些代码托管仓库上的Go项目数量上看,国人编写的Go软件其实已经非常多了。近年来崛起的国内Go开源项目已有不少,特别是(按Star数排列)Gogs、Beego、TiDB、Codis、Pholcus、Hprose、Cyclone等等。他们都已经在国际或国内有了一定的影响力。另外,国人或华人参与的国际Go开源项目更是众多,比如很多人熟知的容器技术领域翘楚Docker、Kubernates、Etcd,等等。


当然,除了一些拔尖的人和拔尖的项目。大多数中国Go程序员和爱好者还是只在国内活跃的。国内的很多地方都自行发起了Go语言用户组,包括但不限于:北京、上海、深圳、杭州,大连、香港等。在各个地方举办的Go语言技术聚会也更加专业、更加频繁,同时规模更大。仅在北京,2016年参加此类聚会或活动的人次就将近400,Go语言北京用户组的微信公众号(golang-beijing)的粉丝数也超过了2000。据悉,在2017年,各地的Go语言用户组还会有更大的动作。


我个人认为,如今Go语言的国内推广已经基本完成了科普阶段,现在我们可以实行更加轻松的推波助澜、顺水推舟的推广策略了。由于Go语言的优秀以及不断的进化,现在自发地关注Go语言的人越来越多了,尤其是在高等学府和编程新手的人群中。


Go语言很好学,配套工具完善,开发和运行效率高,应用领域众多,国内社区也很活跃,有各种各样的中文资料和教程,进阶并不难,其工程化理念也相当得民心。如果你不是一点时间都没有的话,我建议你学一学这门简约、高效的编程语言。在互联网时代,尤其是是移动互联网时代,它已经大有作为。即使对于炙手可热的大数据、微服务等新型领域和理念而言,它也是一个相当重要的技术栈。甚至在即将爆发的人工智能和机器人大潮,我相信,Go语言也必会大放异彩!


作者介绍


郝林,Go语言北京用户组的发起人,极客学院Go语言课程顾问,著有图灵原创图书《Go并发编程实战》,同时也是在线免费教程《Go命令教程》和《Go语言第一课》的作者。目前在微赛时代任平台技术负责人。


参考文献


Go 1.6 Release Notes: https://tip.golang.org/doc/go1.6


Go 1.7 Release Notes: https://tip.golang.org/doc/go1.7


Go 1.8 Release Notes(Beta): https://tip.golang.org/doc/go1.8


The State of Go(2016): https://talks.golang.org/2016/state-of-go.slide


来自:http://www.infoq.com/cn/articles/2016-review-go

GIN API Framework是一款专为Go Gin 框架打造的API Framework

回复

edisonlz 发起了问题 • 3 人关注 • 0 个回复 • 287 次浏览 • 2016-12-15 14:16 • 来自相关话题

参加 Go 官方 2016 用户问卷调查,一起来完善推广 Go

songtianyi 回复了问题 • 2 人关注 • 1 个回复 • 262 次浏览 • 2016-12-14 12:40 • 来自相关话题

将项目中的日志包,替换为beego下的logs,性能提升20-30%

kakashi 发表了文章 • 9 个评论 • 287 次浏览 • 2016-12-12 18:20 • 来自相关话题

将项目中的日志包,替换为beego下的logs,性能提升20-30%,可见自己原来的代码写的有多烂

将项目中的日志包,替换为beego下的logs,性能提升20-30%,可见自己原来的代码写的有多烂