每日新闻

每日新闻

GoCN每日新闻资讯
有问必答

有问必答

Go相关的问题,技术相关的问题
文章分享

文章分享

技术文章分享,让知识传播给更多的人
招聘应聘

招聘应聘

为Gopher服务的招聘应聘平台

[译]空结构体

文章分享itfanr 发表了文章 • 12 个评论 • 7106 次浏览 • 2016-10-16 21:45 • 来自相关话题

这篇文章探讨了我喜欢的Go数据类型,空结构体。 空结构体是一个没有field的[结构体类型](http://golang.org/ref/spec#Struct_types)。这里有几个例子,有命名和匿名形式: ...查看全部
这篇文章探讨了我喜欢的Go数据类型,空结构体。

空结构体是一个没有field的[结构体类型](http://golang.org/ref/spec#Struct_types)。这里有几个例子,有命名和匿名形式:

```go
type Q struct{}
var q struct{}
```

所以,如果空结构体没有成员,我们该怎么使用它?

# width

在深入研究空结构体本身前,我想简要讨论下`width`。

术语width来自于gc编译器,尽管它的词源可能追溯到几十年年。

width描述了类型实例占用的字节数目。因为一个进程的地址空间是一维的,我认为witdh比size更合适。

width一个类型的属性。因为Go程序的每个值都有一个类型,值类型定义了它的witdh,一般是8比特的倍数。

我们可以发现任何值的宽度,它的类型的width使用unsafe.Sizeof()函数:

```go
var s string
var c complex128
fmt.Println(unsafe.Sizeof(s)) // prints 8
fmt.Println(unsafe.Sizeof(c)) // prints 16
```


[http://play.golang.org/p/4mzdOKW6uQ](http://play.golang.org/p/4mzdOKW6uQ)

数组类型的width是它的元素类型的倍数:

```go
var a [3]uint32
fmt.Println(unsafe.Sizeof(a)) // prints 12
```

[http://play.golang.org/p/YC97xsGG73](http://play.golang.org/p/YC97xsGG73)

结构体提供了更灵活的方式来定义组合类型,它的width是所有组成类型的width的总和,加上padding:

```go
type S struct {
a uint16
b uint32
}
var s S
fmt.Println(unsafe.Sizeof(s)) // prints 8, not 6
```

~~上面的例子演示了padding的一方面,值必须在内存中对齐为它的width的倍数。在这个场景中,在a和b中间被编译器加入了2个字节的padding。~~

更新:Russ Cox已经解释了width和对齐无关。你可以阅读[下面的评论](http://dave.cheney.net/2014/03/25/the-empty-struct#comment-2815)。

# 空类型

现在,我们已经探讨了width,很明显空类型的width是零。它占用了零字节的存储空间:

```go
var s struct{}
fmt.Println(unsafe.Sizeof(s)) // prints 0
```

因为空类型占用了零字节,所以它不需要填充。这样,空结构体组成的一个结构体也不占用存储空间:

```go
type S struct {
A struct{}
B struct{}
}
var s S
fmt.Println(unsafe.Sizeof(s)) // prints 0
```

http://play.golang.org/p/PyGYFmPmMt

# 我们可以用空类型做什么

适用于Go语言的正交性,空类型和其他类型一样,是一个结构类型。你所使用的正常的结构体的所有的属性适用于空的结构。

你可以声明一个结构体数组struct{}s,但是他们当然不会占用存储空间:

```go
var x [1000000000]struct{}
fmt.Println(unsafe.Sizeof(x)) // prints 0
```

http://play.golang.org/p/0lWjhSQmkc

struct{}s的切片仅仅消耗他们的slice头的空间。就像上面演示的那样,他们的后端数组不消耗空间:

```go
var x = make([]struct{}, 1000000000)
fmt.Println(unsafe.Sizeof(x)) // prints 12 in the playground
```

http://play.golang.org/p/vBKP8VQpd8

当然,正常的子切片,内置的len和cap和预期一样工作:

```go
var x = make([]struct{}, 100)
var y = x[:50]
fmt.Println(len(y), cap(y)) // prints 50 100
```

http://play.golang.org/p/8cO4SbrWVP

你可以获取struct{}值的地址,当它的可以[地址化](http://golang.org/ref/spec#Address_operators),就像其他值一样:

```go
var a struct{}
var b = &a
```

有意思的是,两个struct{}值的地址可能是相同的:

```go
var a, b struct{}
fmt.Println(&a == &b) // true
```

[http://play.golang.org/p/uMjQpOOkX1](http://play.golang.org/p/uMjQpOOkX1)

对于[]struct{}s,这个属性也是可见的:

```go
a := make([]struct{}, 10)
b := make([]struct{}, 20)
fmt.Println(&a == &b) // false, a and b are different slices
fmt.Println(&a[0] == &b[0]) // true, their backing arrays are the same
```

http://play.golang.org/p/oehdExdd96

为什么是这样?如果你考虑一下,空结构体不包含成员,所以可以不包含数据。如果空结构体不包含数据,不能决定是否两个struct{}值是否是相同的。它们在效果上,是可替代的。

```go
a := struct{}{} // not the zero value, a real new struct{} instance
b := struct{}{}
fmt.Println(a == b) // true
```

http://play.golang.org/p/K9qjnPiwM8

注意:这个属性不是spec所需要的,但是注意:[Two distinct zero-size variables may have the same address in memory.](http://golang.org/ref/spec#Size_and_alignment_guarantees)

# struct{} 作为 method receiver

现在,我们已经演示了空结构体有任何其他类型一样的行为,因此,我们可以把它们作为函数接收者来使用:

```go
type S struct{}

func (s *S) addr() { fmt.Printf("%p\n", s) }

func main() {
var a, b S
a.addr() // 0x1beeb0
b.addr() // 0x1beeb0
}
```

http://play.golang.org/p/YSQCczP-Pt

在这个例子中,展示了all zero sized值的地址为0x1beeb0。精确的地址可能因Go的版本而不同。

# 封装

谢谢你的阅读。本文已接近800字,比预期更多,我还有更多的计划。

尽管本文关注于语言黑盒,有一个空结构体重要的实际用途。chan struct{}用来在不同的go routine之间发送信号。

## 翻译

[本文的中文版在这里](http://www.golangtc.com/t/575442b8b09ecc02f7000057)。

更新:Damian Gryski[指出](https://twitter.com/dgryski/status/448209131334545408)我忽略了 Brad Fitzpatrick的[iter](http://godoc.org/github.com/bradfitz/iter)包。我留下它作为读者的练习来探索Brad的深远影响的贡献。

# 相关文章

1. [Struct composition with Go](http://dave.cheney.net/2015/05/22/struct-composition-with-go)
2. [Friday pop quiz: the smallest buffer](http://dave.cheney.net/2015/06/05/friday-pop-quiz-the-smallest-buffer)
3. [Constant errors](http://dave.cheney.net/2016/04/07/constant-errors)
4. [Stupid Go declaration tricks](http://dave.cheney.net/2013/11/14/stupid-go-declaration-tricks)


[英文原文](http://dave.cheney.net/2014/03/25/the-empty-struct)

如果我翻译得不对,请帮我改善:
https://github.com/itfanr/articles-about-golang/blob/master/2016-10/2.the-empty-struct.md

Linux下一个程序正在写文件,另外一个程序删除该文件,会怎样?

有问必答astaxie 回复了问题 • 3 人关注 • 1 个回复 • 2917 次浏览 • 2016-10-16 20:46 • 来自相关话题

空结构体struct{}的用法

有问必答astaxie 回复了问题 • 8 人关注 • 3 个回复 • 12026 次浏览 • 2016-10-16 20:09 • 来自相关话题

神奇的copy函数

有问必答CTO 回复了问题 • 4 人关注 • 2 个回复 • 2032 次浏览 • 2016-10-16 19:34 • 来自相关话题

glang如何实现小票打印

有问必答jicg 回复了问题 • 4 人关注 • 2 个回复 • 4211 次浏览 • 2016-10-16 12:57 • 来自相关话题

强烈建议 bee 工具创建目录结构时,去掉s

有问必答astaxie 回复了问题 • 3 人关注 • 6 个回复 • 2281 次浏览 • 2016-10-16 11:23 • 来自相关话题

进程退出时如何保证占用的端口完全释放?

有问必答vz 回复了问题 • 8 人关注 • 6 个回复 • 4291 次浏览 • 2016-10-16 08:55 • 来自相关话题

当初就这么入坑了Golang

Golangevolsnow 发表了文章 • 4 个评论 • 1403 次浏览 • 2016-10-16 00:38 • 来自相关话题

当初入坑Golang倒不是工作需要,而是个人兴趣。 因为之前想写个机器人玩,顺便学门编译型语言(之前在写Python),最后挑选了语法简洁,跨平台支持的Go,不曾想最终会为之折服并着迷。。。 周末还写了篇博客 ...查看全部
当初入坑Golang倒不是工作需要,而是个人兴趣。

因为之前想写个机器人玩,顺便学门编译型语言(之前在写Python),最后挑选了语法简洁,跨平台支持的Go,不曾想最终会为之折服并着迷。。。

周末还写了篇博客希望吸引更多的人入坑:smiling_imp::[从零到一:用Golang编写机器人](http://www.jianshu.com/p/46c7d36a95d2)

不知大家是为何入坑Golang的,现在感觉如何?

struct的拷贝问题

有问必答tonyluj 回复了问题 • 8 人关注 • 4 个回复 • 7393 次浏览 • 2016-10-15 23:07 • 来自相关话题

Docker 从入门到实践-2-基本概念

文章分享wwdyy 发表了文章 • 0 个评论 • 1346 次浏览 • 2016-10-15 20:46 • 来自相关话题

# 镜像 ### Docker 包括三个基本概念 镜像(Image) 容器(Container) 仓库(Repository) ...查看全部
# 镜像

### Docker 包括三个基本概念

镜像(Image)
容器(Container)
仓库(Repository)


理解了这三个概念,就理解了 Docker 的整个生命周期。

# Docker 镜像
Docker 镜像就是一个只读的模板。

例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了 Apache 或用户需要的其它应用程序。

镜像可以用来创建 Docker 容器。

Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。


# Docker 容器

Docker 利用容器来运行应用。

容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。

可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

注:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
# Docker 仓库

仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。 国内的公开仓库包括 Docker Pool 等,可以提供大陆用户更稳定快速的访问。

当然,用户也可以在本地网络内创建一个私有仓库。

当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。

注:Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。

go演示工具 - go 社区是如何做演示的?

文章分享bw57899 发表了文章 • 0 个评论 • 2455 次浏览 • 2016-10-15 20:38 • 来自相关话题

golang 有个很简单的演示工具,如果你混go社区的话,这是个很有必要的技能。 :blush: # 安装go 安装go以及设置必要的参数,比如GOPATH。这个就不重复了,相信来这里的都懂。 ...查看全部
golang 有个很简单的演示工具,如果你混go社区的话,这是个很有必要的技能。 :blush:

# 安装go

安装go以及设置必要的参数,比如GOPATH。这个就不重复了,相信来这里的都懂。

# 安装present

```shell
$ go get golang.org/x/net
$ go get golang.org/x/tools
$ go install golang.org/x/tools/cmd/present
```

# 准备 slide 演示文件

```shell
$ cat sample.slide

Title of document
Subtitle of document
15:04 2 Jan 2006
Tags: foo, bar, baz

Author Name
Job title, Company
joe@example.com
http://url/
@twitter_name
Some Text

* Title of slide or section (must have asterisk)

Some Text

* topic 1

- idea 1
- idea 2
- idea 3
```

这是个很简单的演示稿,共三页。第四页是自动生成的。

# 运行 present

因为前面已经安装了present,你可以直接运行它了

```shell
$ present
2016/10/15 11:20:55 Open your web browser and visit http://127.0.0.1:3999
```

# 访问你的演示文件

访问 ghttp://127.0.0.1:3999 即可,会有现成的slide链接显示。

在操作时,移动左右键,你可以看到每个演示稿:

http://127.0.0.1:3999/sample.slide#1

http://127.0.0.1:3999/sample.slide#2

...

# 分享你的演示文档

将你的slide 文件 push 到 github,比如 github.com/DANIU/talks/20161015/sample.slide

那么你应该可以用以下的链接直接访问该演示文档。

http://go-talks.appspot.com/github.com/DANIU/talks/20161015/sample.slide


# present 的格式

请看这里: https://godoc.org/golang.org/x/tools/present

可以支持字体,链接,代码显示(需要将该代码放在同一个目录),部分显示代码,贴图,等等。

实时文件监控

文章分享themoonstone 发表了文章 • 1 个评论 • 4238 次浏览 • 2016-10-15 14:11 • 来自相关话题

由GO构建的实时重载和输出流的文件监控系统、在自定义路径下运行、构建和观察文件更改 ![](https://camo.githubusercontent.com/a6704d699df2b736a8da6c87e4b14d3d4b39bc55/68 ...查看全部
由GO构建的实时重载和输出流的文件监控系统、在自定义路径下运行、构建和观察文件更改
![](https://camo.githubusercontent.com/a6704d699df2b736a8da6c87e4b14d3d4b39bc55/687474703a2f2f692e696d6775722e636f6d2f644a624e5a6a742e676966)
特征:
- 可同时构建,安装,测试,Fmt和运行
- 支持在文件更改时重新加载(重新构建,重新安装和重新运行)
- 支持观看自定义路径
- 支持观看特定的文件扩展名
- 多个项目支持
- 支持输出流
- 执行时间
- 高度可定制
- 快速运行

原文链接:
https://github.com/tockins/realize

Go 中,除了使用缓存池,如何减少 slice 的动态分配?

有问必答tonyluj 回复了问题 • 10 人关注 • 4 个回复 • 2954 次浏览 • 2016-10-15 11:41 • 来自相关话题

golang里 math/rand 和 crypto/rand 区别是什么

有问必答astaxie 回复了问题 • 2 人关注 • 1 个回复 • 4373 次浏览 • 2016-10-15 09:27 • 来自相关话题

10.15 每日早报

文章分享astaxie 发表了文章 • 0 个评论 • 1488 次浏览 • 2016-10-15 08:30 • 来自相关话题

10.15 每日早报 新闻: 1.私有云巨头VMware与公有云老大亚马逊合作,推出混合云服务 2.IBM、谷歌、戴尔、AMD等成立开放技术联盟,发布开放性规范,服务器性能或增10倍 ...查看全部
10.15 每日早报

新闻:

1.私有云巨头VMware与公有云老大亚马逊合作,推出混合云服务

2.IBM、谷歌、戴尔、AMD等成立开放技术联盟,发布开放性规范,服务器性能或增10倍

3.Google Photos基于云端推出重温记忆、生成动图、自动纠图等功能

4.24小时自助健身房Liking健身完成A轮数千万元人民币融资,同创伟业领投

5.高盛宣布上线个人无抵押网络借款平台Marcus,允许自由选择每月还款日和还款计划

6.Pinterest月度活跃用户突破1.5亿,四分之三新用户来自美国以外

7.网易严选宣布为供应商压款支付利息,颠覆传统的361付款方式

8.空客实现3D打印标准化并将其纳入A350 XWB飞机供应链

资源:

中国手机网民网络安全状况报告
http://www.cnnic.net.cn/hlwfzyj/hlwxzbg/ydhlwbg/201610/t20161012_54551.htm

阿里云开源AliSQL数据库
https://github.com/alibaba/AliSQL

注:上述内容来源于互联网,由EGO整理