golang

golang

大家都用什么web框架

技术讨论jongyang 回复了问题 • 9 人关注 • 8 个回复 • 385 次浏览 • 7 小时前 • 来自相关话题

为什么gRPC客户端不提供连接池?

技术讨论caoqianli 回复了问题 • 4 人关注 • 3 个回复 • 234 次浏览 • 4 天前 • 来自相关话题

大家推荐哪种golang包管理方式?

有问必答luw2007 回复了问题 • 22 人关注 • 19 个回复 • 2344 次浏览 • 5 天前 • 来自相关话题

Go GC打印出来的这些信息都是什么含义?

有问必答DefNed 回复了问题 • 10 人关注 • 4 个回复 • 863 次浏览 • 2017-04-15 15:26 • 来自相关话题

请问下有用过caddy server的吗

有问必答kaixinmao 回复了问题 • 2 人关注 • 1 个回复 • 142 次浏览 • 2017-04-12 09:50 • 来自相关话题

Go之旅-for循环

文章分享frankphper 发表了文章 • 0 个评论 • 184 次浏览 • 2017-04-09 22:51 • 来自相关话题

Go语言仅有for一种循环语句,但常用方式都能支持。其中初始化表达式支持函数调用或定义局部变量,需要注意的是初始化语句中的函数仅执行一次,条件表达式中的函数重复执行,规避方式就是在初始化表达式中定义局部变量保存函数返回结果。Go语言中也有goto语句,使... 查看全部

Go语言仅有for一种循环语句,但常用方式都能支持。其中初始化表达式支持函数调用或定义局部变量,需要注意的是初始化语句中的函数仅执行一次,条件表达式中的函数重复执行,规避方式就是在初始化表达式中定义局部变量保存函数返回结果。Go语言中也有goto语句,使用goto语句前,必须先定义标签,标签区分大小写,并且未使用的标签会引发编译错误。和goto定点跳转不同,break、continue用于中断代码块执行。break用于switch、for、select语句,终止整个语句块执行,continue仅用于for循环,终止后续逻辑,立即进入下一轮循环。break和continue配合标签使用,可以在多层嵌套中指定目标层级。



package main

import (
"fmt"
)

// count函数
func count() int {
fmt.Println("count.") // 打印字符串用来查看count函数执行次数
return 3
}

// main函数
func main() {
// for循环
// 初始化表达式,支持函数调用或定义局部变量
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// 类似while循环
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// 类似无限循环
for {
break
}
// 初始化语句中的count函数仅执行一次
for i, c := 0, count(); i < c; i++ {
fmt.Println("a", i)
}

c := 0
// 条件表达式中的count函数重复执行
for c < count() {
fmt.Println("b", c)
c++
}
// 规避条件表达式中的count函数重复执行,在初始化表达式中定义局部变量保存count函数返回结果
count := count()
d := 0
for d < count {
fmt.Println("c", d)
d++
}
// goto定点跳转
// 须先定义标签,并且未用到的标签会引发编译错误
// 不能跳转到其它函数,或内层代码块内
for i := 0; i < 10; i++ {
fmt.Println(i)
if i > 5 {
goto exit
}
}
exit:
fmt.Println("exit.")

// break 用户switch、for、select语句,终止整个语句块执行。continue 仅用于for循环,终止后续逻辑,立即进入下一轮循环
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // 立即进入下一轮循环
}
if i > 5 {
break // 立即终止整个for循环
}
fmt.Println(i)
}
// 配合标签,break和continue可在多层嵌套中指定目标层级
outer:
for i := 0; i < 5; i++ {
for j := 0; j < 10; j++ {
if j > 2 {
fmt.Println()
continue outer
}

if i > 2 {
break outer
}
fmt.Print(i, ":", j, " ")
}
}

}

go 1.8 xml解析不支持cdata

有问必答hmly 回复了问题 • 2 人关注 • 2 个回复 • 197 次浏览 • 2017-04-05 14:02 • 来自相关话题

golang有没有好的开源游戏框架

技术讨论chrislee 回复了问题 • 18 人关注 • 11 个回复 • 2700 次浏览 • 2017-03-25 09:59 • 来自相关话题

beego中路由参数中的controller传入问题

有问必答sundyli 回复了问题 • 2 人关注 • 1 个回复 • 185 次浏览 • 2017-03-24 23:48 • 来自相关话题

beego1.8版本功能征集

文章分享lkhjlbh 回复了问题 • 22 人关注 • 26 个回复 • 2472 次浏览 • 2017-03-22 17:58 • 来自相关话题

实时现在毫秒时钟 RTClock

开源程序Akagi201 发表了文章 • 7 个评论 • 273 次浏览 • 2017-03-22 12:46 • 来自相关话题

找了很久, 没有找到一个在线可用的毫秒时钟. 自己用 websocket 写了一个.

https://github.com/Akagi201/rtc... 查看全部

找了很久, 没有找到一个在线可用的毫秒时钟. 自己用 websocket 写了一个.


https://github.com/Akagi201/rtclock


rtclock



An HTML5 Real Time Clock based on WebSocket



rtclock


Features



  • [x] Use WebSocket to send backend real time clock to frontend.

  • [x] Support go-bindata.


Install



  • go get github.com/Akagi201/rtclock


Build



  • ./gobin.sh (when you modified the html template)

  • go build


Run



  • ./rtclock -h

  • Simple usage: ./rtclock

寻 Go 开源运维监控系统

有问必答ansin 回复了问题 • 7 人关注 • 3 个回复 • 496 次浏览 • 2017-03-17 14:02 • 来自相关话题

Go之旅-Switch

文章分享frankphper 发表了文章 • 0 个评论 • 170 次浏览 • 2017-03-15 22:51 • 来自相关话题

Go之旅-Switch

switch支持初始化语句,注意要用分号结束。后跟条件表达式,如果省略条件表达式,默认为true。不需要显示执行break语句,case执行完毕后自动终端。多个匹配条件,其中一个条件符合即可。case执行中断后,... 查看全部

Go之旅-Switch


switch支持初始化语句,注意要用分号结束。后跟条件表达式,如果省略条件表达式,默认为true。不需要显示执行break语句,case执行完毕后自动终端。多个匹配条件,其中一个条件符合即可。case执行中断后,如果需要继续执行下一个case块的内容,在下一个case块结尾执行fallthrough并且可以在fallthrough前使用break语句阻止。但不继续继续后续case块。


package main

import (
"fmt"
)

func main() {
// 简单声明几个变量
a, b, c, d := 1, 2, 3, 4
switch x := 2; x { // switch支持初始化语句,注意要用分号结束。后跟条件表达式,如果省略条件表达式,默认为true。
case a:
fmt.Println("a")
// break // 不需要显示执行break语句,case执行完毕后自动终端。
case a, b: // 多个匹配条件,其中一个条件符合即可。
fmt.Println("b")
fallthrough // case执行中断后,如果需要继续执行下一个case块的内容,在下一个case块结尾执行fallthrough并且可以在fallthrough前使用break语句阻止。但不继续继续后续case块。
case c:
fmt.Println("c")
case d:
fmt.Println("d")
case 5:
fmt.Println("e")
//case 5, 6: // 支持常量,但不能出现重复常量
// fmt.Println("f")
default:
fmt.Println("x") // 只有全部匹配失败后,才会执行default块。
}
}

关于go qt

有问必答stirlingx 回复了问题 • 5 人关注 • 6 个回复 • 438 次浏览 • 2017-03-13 19:03 • 来自相关话题

Go之旅-常量

文章分享frankphper 发表了文章 • 2 个评论 • 162 次浏览 • 2017-03-12 16:42 • 来自相关话题

Go之旅-常量

常量是指程序运行时不可改变的值,常量必须初始化值,定义常量可以指定类型,编译器也可以通过常量初始化值做类型推断。在函数代码块中定义常量,不被使用也不会出现编译错误。在常量组中如果不指定常量类型和初始化值,那么常量会和上一... 查看全部

Go之旅-常量


常量是指程序运行时不可改变的值,常量必须初始化值,定义常量可以指定类型,编译器也可以通过常量初始化值做类型推断。在函数代码块中定义常量,不被使用也不会出现编译错误。在常量组中如果不指定常量类型和初始化值,那么常量会和上一行的非空常量值相同。


// 声明包main
package main

// 导入包
import (
"fmt"
)

// 定义常量
const a = 10 // 必须赋值,可指定类型,也可以编译器通过初始化值类型推断
const b = "Hello World"
const c = false
const d, e = 1, 10

// 常量组
const (
f = true
g = 100
)

// 定义函数main
func main() {
// 函数块中定义的常量,不适用也不会出现编译错误
const (
h = 1
i // 在常量组中不指定常量类型和初始化值,会和上一行非空的常量值相同。
j
k
)
const g = "Hello World"
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(d, e)
fmt.Println(f, g)
fmt.Println(i)
fmt.Println(j)
fmt.Println(k)
}
条新动态, 点击查看
bigwhite

bigwhite 回答了问题 • 2016-10-11 13:03 • 8 个回复 不感兴趣

怎么学习golang?

赞同来自:

记得早期接触go时,看的是Golang之父之一的Rob Pike的Go course 3部曲(3个ppt),如果你没有,可以到[这里](https://pan.baidu.com/s/1miFEDJy)下载(注意:由于rob pike的这个ppt在go 1之前... 显示全部 »
记得早期接触go时,看的是Golang之父之一的Rob Pike的Go course 3部曲(3个ppt),如果你没有,可以到[这里](https://pan.baidu.com/s/1miFEDJy)下载(注意:由于rob pike的这个ppt在go 1之前发布的,ppt上的有些语法与go 1有少许差别,注意识别)。

要想深入了解Go,写出idiomatic的golang代码,官方doc:effective go, go faq,以及go language specification也是不可或缺的。

之后再系统的学习后的资料,建议看k&a写的go圣经-the go programming language、
《Go in action》 以及国内雨痕大师的《go语言学习笔记》(尤其是代码分析的部分),学习笔记一书适合稍微有些go经验,且抱着极大热情挖掘go runtime背后的原理的人去学习。

剩下的就是不断的去用go coding, coding, coding了,无捷径。
astaxie

astaxie 回答了问题 • 2016-10-11 21:41 • 9 个回复 不感兴趣

golang 的channel是否适合做消息队列?

赞同来自:

我猜你看到的文章的担心是万一程序挂了怎么办,在缓冲channel里面的数据就可能丢失了,如果这个是可以忍受的话其实是非常适合做消息队列的
我猜你看到的文章的担心是万一程序挂了怎么办,在缓冲channel里面的数据就可能丢失了,如果这个是可以忍受的话其实是非常适合做消息队列的
name5566

name5566 回答了问题 • 2016-10-12 11:36 • 11 个回复 不感兴趣

golang有没有好的开源游戏框架

赞同来自:

> 使用 Leaf 已知的上线项目:
> * 2014 年,某手游(棋牌)项目上线
> * 2016 年,某 H5 手游项目上线
> * 2016 年,某卡牌手游项目上线
> 正在研发项目 N 个,已知情况 N >= 4

... 显示全部 »
> 使用 Leaf 已知的上线项目:
> * 2014 年,某手游(棋牌)项目上线
> * 2016 年,某 H5 手游项目上线
> * 2016 年,某卡牌手游项目上线
> 正在研发项目 N 个,已知情况 N >= 4

来自:https://github.com/name5566/leaf/wiki
leoliu

leoliu 回答了问题 • 2016-10-12 13:44 • 22 个回复 不感兴趣

求一些golang的教程,书籍也可以

赞同来自:

《The Golang Programming Language》
《Golang 学习笔记》
《The Golang Programming Language》
《Golang 学习笔记》
yougg

yougg 回答了问题 • 2016-10-14 10:01 • 70 个回复 不感兴趣

大家说说看都用啥写Go

赞同来自:

# IDEA大法好
# 天灭vscode 退软保平安
# 人在做,天在看 中文乱码留祸患
# 界面卡顿天地灭 赶紧卸载保平安
# 诚心诚念IDEA好 JetBrains大法平安保
# 众生皆为IDEA来 现世险恶忘前缘
# 开源为你说真相 教你脱险莫拒绝
# ... 显示全部 »
# IDEA大法好
# 天灭vscode 退软保平安
# 人在做,天在看 中文乱码留祸患
# 界面卡顿天地灭 赶紧卸载保平安
# 诚心诚念IDEA好 JetBrains大法平安保
# 众生皆为IDEA来 现世险恶忘前缘
# 开源为你说真相 教你脱险莫拒绝
# 早日不做软粉,早日获得新生
# 上网搜索“九评纳德拉”
# 有 真 相
sryan

sryan 回答了问题 • 2016-10-13 11:44 • 7 个回复 不感兴趣

golang 如何动态创建struct

赞同来自:

静态语言貌似不能直接实现
可以自己实现个map[string]func(string)interface{}
将要动态生成的结构体的函数注册上去
通过string来调用相应的函数来获取对应的结构体
静态语言貌似不能直接实现
可以自己实现个map[string]func(string)interface{}
将要动态生成的结构体的函数注册上去
通过string来调用相应的函数来获取对应的结构体
astaxie

astaxie 回答了问题 • 2016-10-13 22:04 • 12 个回复 不感兴趣

想用golang写个分布式的监控,大神给点建议

赞同来自:

这个问题很有意思,很多场景设计都会来考虑拉和推两种方案,我分别对拉和推两种的优缺点对比以下,你自己权衡一下,欢迎大家继续补充

## 拉的方案(不写agent)
优点:
- 不需要agent,不需要再部署新的程序

缺点:
- 网络中断的情况下,就无法监控机器... 显示全部 »
这个问题很有意思,很多场景设计都会来考虑拉和推两种方案,我分别对拉和推两种的优缺点对比以下,你自己权衡一下,欢迎大家继续补充

## 拉的方案(不写agent)
优点:
- 不需要agent,不需要再部署新的程序

缺点:
- 网络中断的情况下,就无法监控机器的信息

## 推的方案(agent)
优点:
- 本地运行,在和中控机失去网络连接的时候还是可以继续保存监控数据

缺点:
- 需要部署agent,如果机器多得话将来升级也是比较麻烦

拉取和推送其实大家可以考虑,微博的follow逻辑,直播流里面也有同样的问题,很多场景都会遇到

至于说第二种方案走什么协议,这种程序我建议走tcp协议,HTTP的话相对重了一点。
sheepbao

sheepbao 回答了问题 • 2016-10-30 20:16 • 15 个回复 不感兴趣

字符串连接哪一种方式最高效

赞同来自:

```go
package main

import (
"bytes"
"fmt"
"strings"
"time"
)

var way map[int]string
... 显示全部 »
```go
package main

import (
"bytes"
"fmt"
"strings"
"time"
)

var way map[int]string

func benchmarkStringFunction(n int, index int) (d time.Duration) {
v := "ni shuo wo shi bu shi tai wu liao le a?"
var s string
var buf bytes.Buffer

t0 := time.Now()
for i := 0; i < n; i++ {
switch index {
case 0: // fmt.Sprintf
s = fmt.Sprintf("%s[%s]", s, v)
case 1: // string +
s = s + "[" + v + "]"
case 2: // strings.Join
s = strings.Join([]string{s, "[", v, "]"}, "")
case 3: // stable bytes.Buffer
buf.WriteString("[")
buf.WriteString(v)
buf.WriteString("]")
}

}
d = time.Since(t0)
if index == 3 {
s = buf.String()
}
fmt.Printf("string len: %d\t", len(s))
fmt.Printf("time of [%s]=\t %v\n", way[index], d)
return d
}

func main() {
way = make(map[int]string, 5)
way[0] = "fmt.Sprintf"
way[1] = "+"
way[2] = "strings.Join"
way[3] = "bytes.Buffer"

k := 4
d := [5]time.Duration{}
for i := 0; i < k; i++ {
d[i] = benchmarkStringFunction(10000, i)
}
}

```
结果:
```
string len: 410000 time of [fmt.Sprintf]= 426.001476ms
string len: 410000 time of [+]= 307.044147ms
string len: 410000 time of [strings.Join]= 738.44362ms
string len: 410000 time of [bytes.Buffer]= 742.248µs
```
* strings.Join 最慢
* fmt.Sprintf 和 string + 差不多
* bytes.Buffer又比上者快约500倍
CodyGuo

CodyGuo 回答了问题 • 2016-10-30 12:57 • 4 个回复 不感兴趣

Go里面如何写多行的字符串吗?

赞同来自:

```go
`line 1
line 2
line 3`
```
```go
`line 1
line 2
line 3`
```
philosophia14

philosophia14 回答了问题 • 2016-11-05 00:30 • 3 个回复 不感兴趣

新版本Go将会对database/sql进行大量改进

赞同来自:

但愿不要多改..
但愿不要多改..
zdreamx

zdreamx 回答了问题 • 2016-11-08 11:27 • 26 个回复 不感兴趣

beego1.8版本功能征集

赞同来自:

orm有没有考虑分表分区分库的优化或支持
orm有没有考虑分表分区分库的优化或支持
println 是把结果输出到 standard error

fmt.Println 是把结果输出到 standard output
println 是把结果输出到 standard error

fmt.Println 是把结果输出到 standard output

大家是如何处理 golang web 应用静态资源的?

技术讨论astaxie 回复了问题 • 4 人关注 • 1 个回复 • 628 次浏览 • 2016-10-14 13:08 • 来自相关话题

Python 程序员的 Golang 学习指南(II): 开发环境搭建

文章分享Cloudinsight 发表了文章 • 0 个评论 • 910 次浏览 • 2016-10-12 15:44 • 来自相关话题

Authors: startover

Authors: startover





上一篇文章我们已经对 Golang 有了初步的了解,这篇主要介绍如何在 Ubuntu 14.04 上搭建 Golang 开发环境。


安装 Golang


这里就按照官方文档进行安装即可,如下:



  • 下载并解压安装包到指定目录


$ wget https://storage.googleapis.com ... ar.gz
$ tar -C /usr/local -xzf go1.6.3.linux-amd64.tar.gz


  • 设置 PATH


$ echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
$ source ~/.bashrc


  • 验证安装


$ go version
go version go1.6.3 linux/amd64

环境变量设置


$ echo "export GOROOT=/usr/local/go" >> ~/.bashrc
$ echo "export GOPATH=$HOME/go" >> ~/.bashrc
$ source ~/.bashrc

其中,GOROOT 为 Golang 的安装目录,只有当 Golang 安装到除 /usr/local 之外的路径时需要设置,反之则不用设置,GOPATH 是 Golang 的开发目录,详细可参考官方文档


开发工具


工欲善其事,必先利其器,作为一名伪 VIMer,这里主要介绍下如何在 Vim 下配置 Golang 开发环境。


由于之前一直使用 k-vim 作为 Python 开发环境,而 k-vim 已经集成了当前使用最为广泛的用于搭建 Golang 开发环境的 vim 插件 vim-go,只是默认没有开启,需要我们手动进行相关设置。


k-vim 中开启 Golang 语言的支持,非常简单,如下:



  • 修改 ~/.vimrc.bundles(开启 golang 支持,并修改 vim-go 的默认配置,增加快捷键配置等)。


let g:bundle_groups=['python', 'javascript', 'markdown', 'html', 'css', 'tmux', 'beta', 'json', 'golang']

" vimgo {{{
let g:go_highlight_functions = 1
let g:go_highlight_methods = 1
let g:go_highlight_structs = 1
let g:go_highlight_operators = 1
let g:go_highlight_build_constraints = 1

let g:go_fmt_fail_silently = 1
let g:go_fmt_command = "goimports"
let g:syntastic_go_checkers = ['golint', 'govet', 'errcheck']

" vim-go custom mappings
au FileType go nmap <Leader>s <Plug>(go-implements)
au FileType go nmap <Leader>i <Plug>(go-info)
au FileType go nmap <Leader>gd <Plug>(go-doc)
au FileType go nmap <Leader>gv <Plug>(go-doc-vertical)
au FileType go nmap <leader>r <Plug>(go-run)
au FileType go nmap <leader>b <Plug>(go-build)
au FileType go nmap <leader>t <Plug>(go-test)
au FileType go nmap <leader>c <Plug>(go-coverage)
au FileType go nmap <Leader>ds <Plug>(go-def-split)
au FileType go nmap <Leader>dv <Plug>(go-def-vertical)
au FileType go nmap <Leader>dt <Plug>(go-def-tab)
au FileType go nmap <Leader>e <Plug>(go-rename)
au FileType go nnoremap <leader>gr :GoRun %<CR>
" }}}



  • 在 Vim 内执行 :PlugInstall,安装 vim-go




  • 在 Vim 内执行 :GoInstallBinaries,下载并安装 vim-go 依赖的二进制工具,goimportsgolint 等。



  • 安装 gotags,使 tagbar 配置生效。


$ go get -u github.com/jstemmer/gotags

我们来看一下最终效果:


Image of Golang Environment in Vim


编写第一个程序


进入工作目录,新建文件 hello.go,如下:


$ cd $GOPATH
$ vim hello.go
package main

import "fmt"

func main() {
fmt.Println("Hello, World!")
}

运行程序:


$ go run hello.go
Hello, World!



本文章为 Cloudinsight 技术团队工程师原创,更多技术文章可访问 Cloudinsight 技术博客Cloudinsight 为可视化系统监控工具,涵盖 Windows、Linux 操作系统,用 Golang 开发的 Cloudinsight Agent 正式开源了,欢迎 fork,Github:https://github.com/cloudinsight/cloudinsight-agent


golang-for-pythonistas 系列持续更新中,欢迎关注~

Python 程序员的 Golang 学习指南(I): Go 之初体验

文章分享Cloudinsight 发表了文章 • 2 个评论 • 832 次浏览 • 2016-10-12 15:27 • 来自相关话题

Authors: startover

Authors: startover





Go 语言简介


Go,又称 golang,是 Google 开发的一种静态强类型,编译型,并发型,并具有垃圾回收功能的编程语言。


Go 语言于2009年11月正式宣布推出,自2012年发布1.0,最新稳定版1.7。目前,Go的相关工具和生态已逐渐趋于完善,也不乏重量级项目,如 Docker, Kubernetes, Etcd, InfluxDB 等。


Go 语言能解决什么样的问题


同绝大多数通用型编程语言相比,Go 语言更多的是为了解决我们在构建大型服务器软件过程中所遇到的软件工程方面的问题而设计的。乍看上去,这么讲可能会让人感觉 Go 非常无趣且工业化,但实际上,在设计过程中就着重于清晰和简洁,以及较高的可组合性,最后得到的反而会是一门使用起来效率高而且很有趣的编程语言,很多程序员都会发现,它有极强的表达力而且功能非常强大。


总结为以下几点:



  • 清晰的依赖关系

  • 清晰的语法

  • 清晰的语义

  • 偏向组合而不是继承

  • 提供简单的编程模型(垃圾回收、并发)

  • 强大的内置工具(gofmt、godoc、gofix等)


建议有兴趣的同学看看 Go在谷歌:以软件工程为目的的语言设计


Go 语言相对 Python 有哪些优势


这里引用一段知乎上某大牛的回答,如下:




  • 部署简单。Go 编译生成的是一个静态可执行文件,除了 glibc 外没有其他外部依赖。这让部署变得异常方便:目标机器上只需要一个基础的系统和必要的管理、监控工具,完全不需要操心应用所需的各种包、库的依赖关系,大大减轻了维护的负担。这和 Python 有着巨大的区别。由于历史的原因,Python 的部署工具生态相当混乱【比如 setuptools, distutils, pip, buildout 的不同适用场合以及兼容性问题】。官方 PyPI 源又经常出问题,需要搭建私有镜像,而维护这个镜像又要花费不少时间和精力。




  • 并发性好。Goroutine 和 channel 使得编写高并发的服务端软件变得相当容易,很多情况下完全不需要考虑锁机制以及由此带来的各种问题。单个 Go 应用也能有效的利用多个 CPU 核,并行执行的性能好。这和 Python 也是天壤之比。多线程和多进程的服务端程序编写起来并不简单,而且由于全局锁 GIL 的原因,多线程的 Python 程序并不能有效利用多核,只能用多进程的方式部署;如果用标准库里的 multiprocessing 包又会对监控和管理造成不少的挑战【我们用的 supervisor 管理进程,对 fork 支持不好】。部署 Python 应用的时候通常是每个 CPU 核部署一个应用,这会造成不少资源的浪费,比如假设某个 Python 应用启动后需要占用 100MB 内存,而服务器有 32 个 CPU 核,那么留一个核给系统、运行 31 个应用副本就要浪费 3GB 的内存资源。




  • 良好的语言设计。从学术的角度讲 Go 语言其实非常平庸,不支持许多高级的语言特性;但从工程的角度讲,Go 的设计是非常优秀的:规范足够简单灵活,有其他语言基础的程序员都能迅速上手。更重要的是 Go 自带完善的工具链,大大提高了团队协作的一致性。比如 gofmt 自动排版 Go 代码,很大程度上杜绝了不同人写的代码排版风格不一致的问题。把编辑器配置成在编辑存档的时候自动运行 gofmt,这样在编写代码的时候可以随意摆放位置,存档的时候自动变成正确排版的代码。此外还有 gofix, govet 等非常有用的工具。



  • 执行性能好。虽然不如 C 和 Java,但通常比原生 Python 应用还是高一个数量级的,适合编写一些瓶颈业务。内存占用也非常省。


从个人对 Golang 的初步使用来说,体验还是相当不错的,但是也有下面几点需要注意:




  • 驼峰式命名风格(依据首字母大小写来决定其是否能被其他包引用),但我更喜欢 Python 的小写字母加下划线命名风格。




  • 没有好用的包管理器,Golang 官方也没有推荐最佳的包管理方案,目前公认的比较好用的有 Godeps, Govendor 及 Glide,而 Python 的包管理器 pip 已形成自己的一套标准。




  • 多行字符串的变量声明需要用反引号(`),Python 里是三个双引号("""),参考http://stackoverflow.com/questions/7933460/how-do-you-write-multiline-strings-in-go




  • Golang 中的类型匹配是很严格的,不同的类型之间通常需要手动转换,所以在字符串拼接时往往需要对整型进行显式转换,如 fmt.Println("num: " + strconv.Itoa(1))



  • Golang 语言语法里的语法糖并不多,如在 Python 中很流行的 map, reduce, range 等,在 Golang 里都没有得到支持。


另外,推荐阅读 Golang 新手开发者要注意的陷阱和常见错误


学习资料推荐


建议先把 Go 的官方文档过一遍,主要有以下几项:



官方文档看完后,基本也算入门了,这时候可以看看 Go 的示例代码,或者去 Project Euler 刷刷题。


当然也可以去知乎看看大牛们都是如何学习的,链接 https://www.zhihu.com/question/23486344


总结


虽然 Go 有很多被诟病的地方,比如 GC 和对错误的处理方式,但没有任何语言是完美的,从实用角度来讲,Go 有着不输于 Python 的开发效率,完善的第三方工具,以及强大的社区支持,这些就足够了。


相关链接:

https://golang.org/doc/

https://talks.golang.org/2012/splash.article

https://www.zhihu.com/question/21409296

https://www.zhihu.com/question/23486344

http://stackoverflow.com/questions/7933460/how-do-you-write-multiline-strings-in-go

http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/

http://www.oschina.net/translate/go-at-google-language-design-in-the-service-of-software-engineering




本文章为 Cloudinsight 技术团队工程师原创,更多技术文章可访问 Cloudinsight 技术博客Cloudinsight 为可视化系统监控工具,涵盖 Windows、Linux 操作系统,用 Golang 开发的 Cloudinsight Agent 正式开源了,欢迎 fork,Github:https://github.com/cloudinsight/cloudinsight-agent


golang-for-pythonistas 系列持续更新中,欢迎关注~

求一些golang的教程,书籍也可以

有问必答titian 回复了问题 • 31 人关注 • 22 个回复 • 2146 次浏览 • 2016-11-06 14:35 • 来自相关话题

golang有没有好的开源游戏框架

技术讨论chrislee 回复了问题 • 18 人关注 • 11 个回复 • 2700 次浏览 • 2017-03-25 09:59 • 来自相关话题

为什么Go里面大多数的接口返回的是int类型

有问必答negronihe 回复了问题 • 4 人关注 • 3 个回复 • 1177 次浏览 • 2016-10-16 13:06 • 来自相关话题

大家推荐哪种golang包管理方式?

有问必答luw2007 回复了问题 • 22 人关注 • 19 个回复 • 2344 次浏览 • 5 天前 • 来自相关话题

大家都用什么web框架

回复

技术讨论jongyang 回复了问题 • 9 人关注 • 8 个回复 • 385 次浏览 • 7 小时前 • 来自相关话题

为什么gRPC客户端不提供连接池?

回复

技术讨论caoqianli 回复了问题 • 4 人关注 • 3 个回复 • 234 次浏览 • 4 天前 • 来自相关话题

大家推荐哪种golang包管理方式?

回复

有问必答luw2007 回复了问题 • 22 人关注 • 19 个回复 • 2344 次浏览 • 5 天前 • 来自相关话题

Go GC打印出来的这些信息都是什么含义?

回复

有问必答DefNed 回复了问题 • 10 人关注 • 4 个回复 • 863 次浏览 • 2017-04-15 15:26 • 来自相关话题

请问下有用过caddy server的吗

回复

有问必答kaixinmao 回复了问题 • 2 人关注 • 1 个回复 • 142 次浏览 • 2017-04-12 09:50 • 来自相关话题

go 1.8 xml解析不支持cdata

回复

有问必答hmly 回复了问题 • 2 人关注 • 2 个回复 • 197 次浏览 • 2017-04-05 14:02 • 来自相关话题

golang有没有好的开源游戏框架

回复

技术讨论chrislee 回复了问题 • 18 人关注 • 11 个回复 • 2700 次浏览 • 2017-03-25 09:59 • 来自相关话题

beego中路由参数中的controller传入问题

回复

有问必答sundyli 回复了问题 • 2 人关注 • 1 个回复 • 185 次浏览 • 2017-03-24 23:48 • 来自相关话题

beego1.8版本功能征集

回复

文章分享lkhjlbh 回复了问题 • 22 人关注 • 26 个回复 • 2472 次浏览 • 2017-03-22 17:58 • 来自相关话题

寻 Go 开源运维监控系统

回复

有问必答ansin 回复了问题 • 7 人关注 • 3 个回复 • 496 次浏览 • 2017-03-17 14:02 • 来自相关话题

关于go qt

回复

有问必答stirlingx 回复了问题 • 5 人关注 • 6 个回复 • 438 次浏览 • 2017-03-13 19:03 • 来自相关话题

请问有没有比较好的分布式系统监控项目?

回复

开源程序hacpai 回复了问题 • 4 人关注 • 2 个回复 • 325 次浏览 • 2017-03-10 22:40 • 来自相关话题

我的pprof后生成的火焰图,大家帮忙分析分析

回复

有问必答cholerae 回复了问题 • 2 人关注 • 1 个回复 • 397 次浏览 • 2017-03-07 21:18 • 来自相关话题

关于 二维码 解析

回复

技术讨论w07128597 回复了问题 • 7 人关注 • 11 个回复 • 505 次浏览 • 2017-03-04 11:19 • 来自相关话题

字符串连接哪一种方式最高效

回复

有问必答toyijiu 回复了问题 • 21 人关注 • 15 个回复 • 1998 次浏览 • 2017-03-02 21:43 • 来自相关话题

Go之旅-for循环

文章分享frankphper 发表了文章 • 0 个评论 • 184 次浏览 • 2017-04-09 22:51 • 来自相关话题

Go语言仅有for一种循环语句,但常用方式都能支持。其中初始化表达式支持函数调用或定义局部变量,需要注意的是初始化语句中的函数仅执行一次,条件表达式中的函数重复执行,规避方式就是在初始化表达式中定义局部变量保存函数返回结果。Go语言中也有goto语句,使... 查看全部

Go语言仅有for一种循环语句,但常用方式都能支持。其中初始化表达式支持函数调用或定义局部变量,需要注意的是初始化语句中的函数仅执行一次,条件表达式中的函数重复执行,规避方式就是在初始化表达式中定义局部变量保存函数返回结果。Go语言中也有goto语句,使用goto语句前,必须先定义标签,标签区分大小写,并且未使用的标签会引发编译错误。和goto定点跳转不同,break、continue用于中断代码块执行。break用于switch、for、select语句,终止整个语句块执行,continue仅用于for循环,终止后续逻辑,立即进入下一轮循环。break和continue配合标签使用,可以在多层嵌套中指定目标层级。



package main

import (
"fmt"
)

// count函数
func count() int {
fmt.Println("count.") // 打印字符串用来查看count函数执行次数
return 3
}

// main函数
func main() {
// for循环
// 初始化表达式,支持函数调用或定义局部变量
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// 类似while循环
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// 类似无限循环
for {
break
}
// 初始化语句中的count函数仅执行一次
for i, c := 0, count(); i < c; i++ {
fmt.Println("a", i)
}

c := 0
// 条件表达式中的count函数重复执行
for c < count() {
fmt.Println("b", c)
c++
}
// 规避条件表达式中的count函数重复执行,在初始化表达式中定义局部变量保存count函数返回结果
count := count()
d := 0
for d < count {
fmt.Println("c", d)
d++
}
// goto定点跳转
// 须先定义标签,并且未用到的标签会引发编译错误
// 不能跳转到其它函数,或内层代码块内
for i := 0; i < 10; i++ {
fmt.Println(i)
if i > 5 {
goto exit
}
}
exit:
fmt.Println("exit.")

// break 用户switch、for、select语句,终止整个语句块执行。continue 仅用于for循环,终止后续逻辑,立即进入下一轮循环
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // 立即进入下一轮循环
}
if i > 5 {
break // 立即终止整个for循环
}
fmt.Println(i)
}
// 配合标签,break和continue可在多层嵌套中指定目标层级
outer:
for i := 0; i < 5; i++ {
for j := 0; j < 10; j++ {
if j > 2 {
fmt.Println()
continue outer
}

if i > 2 {
break outer
}
fmt.Print(i, ":", j, " ")
}
}

}

实时现在毫秒时钟 RTClock

开源程序Akagi201 发表了文章 • 7 个评论 • 273 次浏览 • 2017-03-22 12:46 • 来自相关话题

找了很久, 没有找到一个在线可用的毫秒时钟. 自己用 websocket 写了一个.

https://github.com/Akagi201/rtc... 查看全部

找了很久, 没有找到一个在线可用的毫秒时钟. 自己用 websocket 写了一个.


https://github.com/Akagi201/rtclock


rtclock



An HTML5 Real Time Clock based on WebSocket



rtclock


Features



  • [x] Use WebSocket to send backend real time clock to frontend.

  • [x] Support go-bindata.


Install



  • go get github.com/Akagi201/rtclock


Build



  • ./gobin.sh (when you modified the html template)

  • go build


Run



  • ./rtclock -h

  • Simple usage: ./rtclock

Go之旅-Switch

文章分享frankphper 发表了文章 • 0 个评论 • 170 次浏览 • 2017-03-15 22:51 • 来自相关话题

Go之旅-Switch

switch支持初始化语句,注意要用分号结束。后跟条件表达式,如果省略条件表达式,默认为true。不需要显示执行break语句,case执行完毕后自动终端。多个匹配条件,其中一个条件符合即可。case执行中断后,... 查看全部

Go之旅-Switch


switch支持初始化语句,注意要用分号结束。后跟条件表达式,如果省略条件表达式,默认为true。不需要显示执行break语句,case执行完毕后自动终端。多个匹配条件,其中一个条件符合即可。case执行中断后,如果需要继续执行下一个case块的内容,在下一个case块结尾执行fallthrough并且可以在fallthrough前使用break语句阻止。但不继续继续后续case块。


package main

import (
"fmt"
)

func main() {
// 简单声明几个变量
a, b, c, d := 1, 2, 3, 4
switch x := 2; x { // switch支持初始化语句,注意要用分号结束。后跟条件表达式,如果省略条件表达式,默认为true。
case a:
fmt.Println("a")
// break // 不需要显示执行break语句,case执行完毕后自动终端。
case a, b: // 多个匹配条件,其中一个条件符合即可。
fmt.Println("b")
fallthrough // case执行中断后,如果需要继续执行下一个case块的内容,在下一个case块结尾执行fallthrough并且可以在fallthrough前使用break语句阻止。但不继续继续后续case块。
case c:
fmt.Println("c")
case d:
fmt.Println("d")
case 5:
fmt.Println("e")
//case 5, 6: // 支持常量,但不能出现重复常量
// fmt.Println("f")
default:
fmt.Println("x") // 只有全部匹配失败后,才会执行default块。
}
}

Go之旅-常量

文章分享frankphper 发表了文章 • 2 个评论 • 162 次浏览 • 2017-03-12 16:42 • 来自相关话题

Go之旅-常量

常量是指程序运行时不可改变的值,常量必须初始化值,定义常量可以指定类型,编译器也可以通过常量初始化值做类型推断。在函数代码块中定义常量,不被使用也不会出现编译错误。在常量组中如果不指定常量类型和初始化值,那么常量会和上一... 查看全部

Go之旅-常量


常量是指程序运行时不可改变的值,常量必须初始化值,定义常量可以指定类型,编译器也可以通过常量初始化值做类型推断。在函数代码块中定义常量,不被使用也不会出现编译错误。在常量组中如果不指定常量类型和初始化值,那么常量会和上一行的非空常量值相同。


// 声明包main
package main

// 导入包
import (
"fmt"
)

// 定义常量
const a = 10 // 必须赋值,可指定类型,也可以编译器通过初始化值类型推断
const b = "Hello World"
const c = false
const d, e = 1, 10

// 常量组
const (
f = true
g = 100
)

// 定义函数main
func main() {
// 函数块中定义的常量,不适用也不会出现编译错误
const (
h = 1
i // 在常量组中不指定常量类型和初始化值,会和上一行非空的常量值相同。
j
k
)
const g = "Hello World"
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(d, e)
fmt.Println(f, g)
fmt.Println(i)
fmt.Println(j)
fmt.Println(k)
}

Go之旅-变量

Golangfrankphper 发表了文章 • 2 个评论 • 180 次浏览 • 2017-03-10 00:03 • 来自相关话题

Go之旅-变量

Go语言变量有固定的数据类型,决定了变量内存的长度和存储格式。Go变量只能修改变量值,不能改变变量的数据类型。Go编译器会把未使用的局部变量当做错误,未使用的全局变量不受影响。

查看全部
					

Go之旅-变量


Go语言变量有固定的数据类型,决定了变量内存的长度和存储格式。Go变量只能修改变量值,不能改变变量的数据类型。Go编译器会把未使用的局部变量当做错误,未使用的全局变量不受影响。


// 声明包main
package main
// 导入包
import(
"fmt"
)
// 定义变量
var a int // 初始化为二进制零值
var b = false // 显示初始化变量的值,可以省略变量类型,由编译器自动类型推断
var c, d = 100, "hello" // 一次定义多个变量,数据类型可以不同
// 定义多个变量,建议使用组的形式定义多个变量
var (
e, f int
g, h = 100, "hello"
)

// 定义函数main
func main() {
// 简短模式声明变量
i := 100
/**
*简短模式声明变量,有以下3个条件
*显示初始化
*不能显示指定数据类型
*只能在函数内部使用
*/
// 多变量赋值
x, y := 1, 10
x, y = x+10, y+1 // 先计算右值,然后再对左边变量赋值,必须保证左右值得数据类型相同
// 打印变量的值
fmt.Println(a);
fmt.Println(b);
fmt.Println(c, d)
fmt.Println(e, f)
fmt.Println(g, h)
fmt.Println(i)
fmt.Println(x, y)
}

今天就先到这,欢迎各位Go语言大神一起交流分享。

使用 Elastic Stack 来监控和调优 Golang 应用程序

文章分享astaxie 发表了文章 • 1 个评论 • 927 次浏览 • 2017-03-05 14:36 • 来自相关话题

Golang 因为其语法简单,上手快且方便部署正被越来越多的开发者所青睐,一个 Golang 程序开发好了之后,势必要关心其运行情况,今天在这里就给大家介绍一下如果使用 Elastic Stack 来分析 Golang 程序的内存使用情况,方便对 Gol... 查看全部

Golang 因为其语法简单,上手快且方便部署正被越来越多的开发者所青睐,一个 Golang 程序开发好了之后,势必要关心其运行情况,今天在这里就给大家介绍一下如果使用 Elastic Stack 来分析 Golang 程序的内存使用情况,方便对 Golang 程序做长期监控进而调优和诊断,甚至发现一些潜在的内存泄露等问题。


Elastic Stack 其实是一个集合,包含 Elasticsearch、Logstash 和 Beats 这几个开源软件,而 Beats 又包含 Filebeat、Packetbeat、Winlogbeat、Metricbeat 和新出的 Heartbeat,呵呵,有点多吧,恩,每个 beat 做的事情不一样,没关系,今天主要用到 Elasticsearch、Metricbeat 和 Kibana 就行了。


Metricbeat 是一个专门用来获取服务器或应用服务内部运行指标数据的收集程序,也是 Golang 写的,部署包比较小才10M 左右,对目标服务器的部署环境也没有依赖,内存资源占用和 CPU 开销也较小,目前除了可以监控服务器本身的资源使用情况外,还支持常见的应用服务器和服务,目前支持列表如下:



  • Apache Module

  • Couchbase Module

  • Docker Module

  • HAProxy Module

  • kafka Module

  • MongoDB Module

  • MySQL Module

  • Nginx Module

  • PostgreSQL Module

  • Prometheus Module

  • Redis Module

  • System Module

  • ZooKeeper Module


当然,也有可能你的应用不在上述列表,没关系,Metricbeat 是可以扩展的,你可以很方便的实现一个模块,而本文接下来所用的 Golang Module 也就是我刚刚为 Metricbeat 添加的扩展模块,目前已经 merge 进入 Metricbeat 的 master 分支,预计会在 6.0 版本发布,想了解是如何扩展这个模块的可以查看 代码路径 和 PR地址。


上面的这些可能还不够吸引人,我们来看一下 Kibana 对 Metricbeat 使用 Golang 模块收集的数据进行的可视化分析吧:



上面的图简单解读一下:
最上面一栏是 Golang Heap 的摘要信息,可以大致了解 Golang 的内存使用和 GC 情况,System 表示 Golang 程序从操作系统申请的内存,可以理解为进程所占的内存(注意不是进程对应的虚拟内存),Bytes allocated 表示 Heap 目前分配的内存,也就是 Golang 里面直接可使用的内存,GC limit 表示当 Golang 的 Heap 内存分配达到这个 limit 值之后就会开始执行 GC,这个值会随着每次 GC 而变化, GC cycles 则代表监控周期内的 GC 次数;


中间的三列分别是堆内存、进程内存和对象的统计情况;Heap Allocated 表示正在用和没有用但还未被回收的对象的大小;Heap Inuse 显然就是活跃的对象大小了;Heap Idle 表示已分配但空闲的内存;


底下两列是 GC 时间和 GC 次数的监控统计,CPUFraction 这个代表该进程 CPU 占用时间花在 GC 上面的百分比,值越大说明 GC 越频繁,浪费更多的时间在 GC 上面,上图虽然趋势陡峭,但是看范围在0.41%~0.52%之间,看起来还算可以,如果GC 比率占到个位数甚至更多比例,那肯定需要进一步优化程序了。


有了这些信息我们就能够知道该 Golang 的内存使用和分配情况和 GC 的执行情况,假如要分析是否有内存泄露,看内存使用和堆内存分配的趋势是否平稳就可以了,另外 GC_Limit 和 Byte Allocation 一直上升,那肯定就是有内存泄露了,结合历史信息还能对不同版本/提交对 Golang 的内存使用和 GC 影响进行分析。


接下来就要给大家介绍如何具体使用了,首先需要启用 Golang 的 expvar 服务,expvar(https://golang.org/pkg/expvar/) 是 Golang 提供的一个暴露内部变量或统计信息的标准包。
使用的方法很简单,只需要在 Golang 的程序引入该包即可,它会自动注册现有的 http 服务上,如下:


import _ "expvar"

如果 Golang 没有启动 http 服务,使用下面的方式启动一个即可,这里端口是 6060,如下:


func metricsHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")

first := true
report := func(key string, value interface{}) {
if !first {
fmt.Fprintf(w, ",\n")
}
first = false
if str, ok := value.(string); ok {
fmt.Fprintf(w, "%q: %q", key, str)
} else {
fmt.Fprintf(w, "%q: %v", key, value)
}
}

fmt.Fprintf(w, "{\n")
monitoring.Do(monitoring.Full, report)
expvar.Do(func(kv expvar.KeyValue) {
report(kv.Key, kv.Value)
})
fmt.Fprintf(w, "\n}\n")
}

func main() {
mux := http.NewServeMux()
mux.HandleFunc("/debug/vars", metricsHandler)
endpoint := http.ListenAndServe("localhost:6060", mux)
}

默认注册的访问路径是/debug/vars, 编译启动之后,就可以通过 http://localhost:6060/debug/vars 来访问 expvar 以 JSON 格式暴露出来的这些内部变量,默认提供了 Golang 的 runtime.Memstats 信息,也就是上面分析的数据源,当然你还可以注册自己的变量,这里暂时不提。


OK,现在我们的 Golang 程序已经启动了,并且通过 expvar 暴露出了运行时的内存使用情况,现在我们需要使用 Metricbeat 来获取这些信息并存进 Elasticsearch。


关于 Metricbeat 的安装其实很简单,下载对应平台的包解压(下载地址:https://www.elastic.co/downloads/beats/metricbeat ),启动 Metricbeat 前,修改配置文件:metricbeat.yml


metricbeat.modules:
- module: golang
metricsets: ["heap"]
enabled: true
period: 10s
hosts: ["localhost:6060"]
heap.path: "/debug/vars"

上面的参数启用了 Golang 监控模块,并且会10秒获取一次配置路径的返回内存数据,我们同样配置该配置文件,设置数据输出到本机的 Elasticsearch:


output.elasticsearch:
hosts: ["localhost:9200"]

现在启动 Metricbeat:


./metricbeat -e -v

现在在 Elasticsearch 应该就有数据了,当然记得确保 Elasticsearch 和 Kibana 是可用状态,你可以在 Kibana 根据数据灵活自定义可视化,推荐使用 Timelion 来进行分析,当然为了方便也可以直接导入提供的样例仪表板,就是上面第一个图的效果。
关于如何导入样例仪表板请参照这个文档:https://www.elastic.co/guide/e ... .html


除了监控已经有的内存信息之外,如果你还有一些内部的业务指标想要暴露出来,也是可以的,通过 expvar 来做同样可以。一个简单的例子如下:


var inerInt int64 = 1024
pubInt := expvar.NewInt("your_metric_key")
pubInt.Set(inerInt)
pubInt.Add(2)

在 Metricbeat 内部也同样暴露了很多内部运行的信息,所以 Metricbeat 可以自己监控自己了。。。
首先,启动的时候带上参数设置pprof监控的地址,如下:


./metricbeat -httpprof="127.0.0.1:6060" -e -v

这样我们就能够通过 http://127.0.0.1:6060/debug/vars">http://127.0.0.1:6060/debug/vars]http://127.0.0.1:6060/debug/vars 访问到内部运行情况了,如下:


{
"output.events.acked": 1088,
"output.write.bytes": 1027455,
"output.write.errors": 0,
"output.messages.dropped": 0,
"output.elasticsearch.publishEvents.call.count": 24,
"output.elasticsearch.read.bytes": 12215,
"output.elasticsearch.read.errors": 0,
"output.elasticsearch.write.bytes": 1027455,
"output.elasticsearch.write.errors": 0,
"output.elasticsearch.events.acked": 1088,
"output.elasticsearch.events.not_acked": 0,
"output.kafka.events.acked": 0,
"output.kafka.events.not_acked": 0,
"output.kafka.publishEvents.call.count": 0,
"output.logstash.write.errors": 0,
"output.logstash.write.bytes": 0,
"output.logstash.events.acked": 0,
"output.logstash.events.not_acked": 0,
"output.logstash.publishEvents.call.count": 0,
"output.logstash.read.bytes": 0,
"output.logstash.read.errors": 0,
"output.redis.events.acked": 0,
"output.redis.events.not_acked": 0,
"output.redis.read.bytes": 0,
"output.redis.read.errors": 0,
"output.redis.write.bytes": 0,
"output.redis.write.errors": 0,
"beat.memstats.memory_total": 155721720,
"beat.memstats.memory_alloc": 3632728,
"beat.memstats.gc_next": 6052800,
"cmdline": ["./metricbeat","-httpprof=127.0.0.1:6060","-e","-v"],
"fetches": {"system-cpu": {"events": 4, "failures": 0, "success": 4}, "system-filesystem": {"events": 20, "failures": 0, "success": 4}, "system-fsstat": {"events": 4, "failures": 0, "success": 4}, "system-load": {"events": 4, "failures": 0, "success": 4}, "system-memory": {"events": 4, "failures": 0, "success": 4}, "system-network": {"events": 44, "failures": 0, "success": 4}, "system-process": {"events": 1008, "failures": 0, "success": 4}},
"libbeat.config.module.running": 0,
"libbeat.config.module.starts": 0,
"libbeat.config.module.stops": 0,
"libbeat.config.reloads": 0,
"memstats": {"Alloc":3637704,"TotalAlloc":155
... ...

比如,上面就能看到output模块Elasticsearch的处理情况,如 output.elasticsearch.events.acked 参数表示发送到 Elasticsearch Ack返回之后的消息。


现在我们要修改 Metricbeat 的配置文件,Golang 模块有两个 metricset,可以理解为两个监控的指标类型,我们现在需要加入一个新的 expvar 类型,这个即自定义的其他指标,相应配置文件修改如下:


- module: golang
metricsets: ["heap","expvar"]
enabled: true
period: 1s
hosts: ["localhost:6060"]
heap.path: "/debug/vars"
expvar:
namespace: "metricbeat"
path: "/debug/vars"

上面的一个参数 namespace 表示自定义指标的一个命令空间,主要是为了方便管理,这里是 Metricbeat 自身的信息,所以 namespace 就是 metricbeat。


重启 Metricbeat 应该就能收到新的数据了,我们前往 Kibana。


这里假设关注 output.elasticsearch.events.acked和
output.elasticsearch.events.not_acked这两个指标,我们在Kibana里面简单定义一个曲线图就能看到 Metricbeat 发往 Elasticsearch 消息的成功和失败趋势。
Timelion 表达式:


.es("metricbeat*",metric="max:golang.metricbeat.output.elasticsearch.events.acked").derivative().label("Elasticsearch Success"),.es("metricbeat*",metric="max:golang.metricbeat.output.elasticsearch.events.not_acked").derivative().label("Elasticsearch Failed")

效果如下:



从上图可以看到,发往 Elasticsearch 的消息很稳定,没有出现丢消息的情况,同时关于 Metricbeat 的内存情况,我们打开导入的 Dashboard 查看:



关于如何使用 Metricbeat 来监控 Golang 应用程序的内容基本上就差不多到这里了,上面介绍了如何基于 expvar 来监控 Golang 的内存情况和自定义业务监控指标,在结合 Elastic Stack 可以快速的进行分析,希望对大家有用。


最后,这个 Golang 模块目前还没 release,估计在 beats 6.0 发布,有兴趣尝鲜的可以自己下载源码打包。

《Go语言实战》GopherChina会员福利

线下活动astaxie 发表了文章 • 2 个评论 • 848 次浏览 • 2017-02-23 09:31 • 来自相关话题

《Go语言实战》这本书出版了,刚和出版社申请了一个我们GopherChina的会员福利,75折,大家可以拿着书来Gopher大会找我签名。http:... 查看全部

《Go语言实战》这本书出版了,刚和出版社申请了一个我们GopherChina的会员福利,75折,大家可以拿着书来Gopher大会找我签名。http://www.epubit.com.cn/book/details/4291 下单输入优惠码:epubit-TRUCP



  • 版权

  • 版权声明

  • 内容提要

  • 译者序

  • 译者简介


  • 前言

  • 致谢

  • 关于本书

  • 关于封面插图

  • 第1章 关于Go语言的介绍

  • 第2章 快速开始一个Go程序

  • 第3章 打包和工具链

  • 第4章 数组、切片和映射

  • 第5章 Go语言的类型系统

  • 第6章 并发

  • 第7章 并发模式

  • 第8章 标准库

  • 第9章 测试和性能


处理文件上传的工具包 - fuh

开源程序lyric 发表了文章 • 0 个评论 • 215 次浏览 • 2017-02-19 11:17 • 来自相关话题

处理文件上传的工具包 - fuh

在平时web开发过程中,总会遇到处理文件上传的场景,每次的处理方式都是以业务为导向进行处理。现在作者就把这一... 查看全部

处理文件上传的工具包 - fuh


在平时web开发过程中,总会遇到处理文件上传的场景,每次的处理方式都是以业务为导向进行处理。现在作者就把这一块单独抽离出来,做成了一个简单的工具包。主要特点是:



  • 支持自定义文件存储

  • 支持自定义文件名

  • 支持自定义文件大小限制


引入简单,方便,欢迎来拍砖!谢谢!


$ go get github.com/LyricTian/fuh

package main

import (
"encoding/json"
"net/http"

"github.com/LyricTian/fuh"
)

func main() {
http.HandleFunc("/fileupload", func(w http.ResponseWriter, r *http.Request) {
finfo, err := fuh.Upload(r, "file", nil, nil)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
json.NewEncoder(w).Encode(finfo)
})

http.ListenAndServe(":8080", nil)
}

dockerSSH用ssh连接到docker

开源程序myml 发表了文章 • 5 个评论 • 245 次浏览 • 2017-02-11 21:59 • 来自相关话题

dockerSSH

用golang.org/x/crypto/ssh 实现的ssh服务器,能直接让你通过ss... 查看全部

dockerSSH


用golang.org/x/crypto/ssh 实现的ssh服务器,能直接让你通过ssh登陆到docker容器内,比如ssh ff756b3ea527@127.0.0.1 会登陆到ID为ff756b3ea527的容器,刚实现的尚不成熟,还有一些功能想去实现,比如scp,sftp

好玩的github项目-用go做个flappy bird

Go开源项目wwdyy 发表了文章 • 1 个评论 • 397 次浏览 • 2017-02-06 22:46 • 来自相关话题

flappy gopher

转自github用户neomede

A flappy bird clone made in go. 查看全部

flappy gopher


转自github用户neomede


A flappy bird clone made in go.


Based on this video and this project by Francesc Campoy, also this project by Sab


Play


Just run "make run" and use any button to jump


github地址:https://github.com/neomede/flappy

golang 特性简介

文章分享sheepbao 发表了文章 • 0 个评论 • 607 次浏览 • 2017-01-22 16:37 • 来自相关话题

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

  • 数组边界检查

gmcache一个用go写的分布式缓存,类似memcached

开源程序stirlingx 发表了文章 • 0 个评论 • 350 次浏览 • 2017-01-19 16:01 • 来自相关话题

主要是用来练手的,欢迎大家仍砖头

  • 使用ectd做服务发现
  • broker作为代理服务器,对client的请求做转发,用一致性hash算法对key映射到后端gmcache。

项目地... 查看全部

主要是用来练手的,欢迎大家仍砖头



  • 使用ectd做服务发现

  • broker作为代理服务器,对client的请求做转发,用一致性hash算法对key映射到后端gmcache。


项目地址:


https://github.com/liyue201/gmcache


Gmcache


A distributed key/value memory cache written in go.


Features



  • Light weight

  • Pure golang

  • Supports set,get and delete

  • Supports grpc and http protocols

  • Scalable architecture


Architecture


gmcache-cluster

Go 通过 Swig 调用 C/C++ 程序

技术讨论Akagi201 发表了文章 • 1 个评论 • 318 次浏览 • 2017-01-18 21:08 • 来自相关话题

项目地址: https://github.com/Akagi201/swiggo


swiggo


Build Status
Go Report Card
GoDoc


Call C/C++ lib with the help of swig


Generate Go package file and C/C++ wrapper file



  • mv interface.swig/interface.swigxx interface.i

  • For C: swig -go -cgo -intgosize 64 interface.i

  • For C++: swig -go -cgo -c++ -intgosize 64 interface.i


Usage



  • go get github.com/Akagi201/swiggo


TODO



  • [ ] Auto gen Go package files for godoc and IDE to browser Go definitions.

力争做最好的go模板引擎

开源程序Lime 发表了文章 • 3 个评论 • 540 次浏览 • 2017-01-17 13:01 • 来自相关话题

一直觉得 go 没有一个好用的模板引擎,渲染 html 的时候特别痛苦,总有一种有力气却使不出来的感觉。

模板引擎一般有两种实现方式,一种是解析 html 语法树,然后根据一定的规则动态的拼接,另外一种是把模板预先生成代码,渲染模板时调用相... 查看全部

一直觉得 go 没有一个好用的模板引擎,渲染 html 的时候特别痛苦,总有一种有力气却使不出来的感觉。


模板引擎一般有两种实现方式,一种是解析 html 语法树,然后根据一定的规则动态的拼接,另外一种是把模板预先生成代码,渲染模板时调用相关的函数即可。


Go 内置的 template 包使用的是第一种方式,不过很多开源项目使用的是第二种方式,比如 quicktemplate 、 gorazor 等。不过这两个可能由于设计的问题,都没有实现模板继承和模板 include ,而且有的语法个人觉得不是太优雅。


所以我想要一个 go 模板,它具备以下特性:


原生的 golang 语法



  • 支持模板植入代码

  • 支持模板继承和 include

  • 高性能

  • 语法简单、优雅

  • 自动编译


基于以上,实现了 hero 模板引擎,用过 nodejs EJS 模板引擎的童鞋应该很容易上手。 hero 目前已经在 http://bthub.io 线上使用。


Github: https://github.com/shiyanhui/hero


Gophers ,欢迎 issues 和 pr ,让我们一起共同打造 golang 最好的模板引擎!