[Go语言]从Docker源码学习Go——指针和Structs
这两天在看reflect这个包在Docker中的使用时,遇到了各种问题,最后虽然知道怎么用了。
但是对于这块的原理还不是太懂,于是把"THE WAY TO GO"中关键的几章看了下。
继续坚持往下写,争取能说明白。
源码
还是先看Docker中源码, docker/api/client/cli.go
type DockerCli struct {
proto string
addr string
configFile *registry.ConfigFile
in io.ReadCloser
out io.Writer
err io.Writer
isTerminal bool
terminalFd uintptr
tlsConfig *tls.Config
scheme string
}
...
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
...
return &DockerCli{
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
isTerminal: isTerminal,
terminalFd: terminalFd,
tlsConfig: tlsConfig,
scheme: scheme,
}
}
先定义了一个struct,然后定义一个初始化的方法(方法内部初始化了一个struct,并返回其地址。)
指针
首先介绍一下go中的指针
我们在程序中定义一个变量,它在内存中被分配了一块空间,这块空间内存储的值就是变量的值,而这块空间的地址就可以赋值给一个指针。
指针内存放的是一个变量的内存地址,而不是真实的变量值。
声明一个指针用下面的方式( type 前面带 * 符号)
var intP *int
给指针赋值用 & 符号
i1 :=
intP = &i1
通过在指针变量前面添加 * 符号,你可以获得指针指向变量的值。
int1 == *(&int1)
在传值过程中尽量使用指针,这可以大大的减少内存开支,并提高传值速度。
不过有一个缺点是,在获得值时,由于多加了一层关系,所以会在这部分的性能上稍微慢一点。
struct使用
struct格式
type identifier struct {
field1 type1
field2 type2
...
}
struct初始化, 看下面例子中的3种情况就明白了。
// main
package main import "strings" type Person struct {
firstName string
lastName string
} func upPerson(p *Person) {
p.firstName = strings.ToUpper(p.firstName)
p.lastName = strings.ToUpper(p.lastName)
} func main() {
//1 - struct as a value type:
var pers1 Person
pers1.firstName = "Lemon"
pers1.lastName = "Bar"
upPerson(&pers1) //2 - struct as a pointer:
pers2 := new(Person)
pers2.firstName = "Lemon"
pers2.lastName = "Bar"
//(*pers2).lastName = "Bar" //this is also valid
upPerson(pers2) //3 - struct as a literal:
pers3 := &Person{"Lemon", "Bar"}
//pers3 := &Person{firstName:"Lemon",lastName:"Bar"} //this is also valid
upPerson(pers3)
}
注:new出来的是指针
我们除了可以直接初始化外,也可以通过定义工厂方法的形式来进行初始化
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
...
}
注:如果想让这个struct在所属的package外,只能通过工厂方法来初始化,可以把struct名字的首字母改成小写,也就是private的,package外就只能通过工厂方法进行初始化了。
匿名fields
匿名的fields可以实现其它语言中继承的功能
package main
type innerS struct {
in1 int
in2 int
}
type outerS struct {
b int
c float32
int //anonymous field
innerS //anonymous field
}
func main() {
outer := new(outerS)
outer.in1 = //outerS.in1 is innerS.in1
outer.in2 = //outerS.in2 is innerS.in2
outer.int = //int is also the anonymous filed name
outer2 := outerS{, 6.7, , innerS{, }} //outerS can also be initialized in this format
}
匿名struct里面的filed就变成外面struct的field。
注:在一个struct内,对于每种类型,只能有一个匿名类型的field。
名字冲突问题
由于一个struct里面可以包含多个匿名的不同类型的struct,那当有名字相同的filed时,go怎么处理呢?
1. outer field比inner field优先级更高,也就是外面的会覆盖掉里面的。
2. 如果两个field层级一样
a. 如果这个field名字,没有被用到的话,不会有问题。
b. 如果被用到了,会有编译错误。
[Go语言]从Docker源码学习Go——指针和Structs的更多相关文章
- [Go语言]从Docker源码学习Go——结构和函数的定义
Docker在最近很火,而作为Docker的开发语言-Go也再次被大家提到. 已经使用Docker一段时间了,但是对于源码,尤其是其开发语言Go却一直是一知半解. 最近准备利用空余时间从Docker源 ...
- [Go语言]从Docker源码学习Go——function和method
function和method关系 method是针对某一类型定义的function, function可以单独调用,method必须针对某一类型的实例进行调用 //function 调用方式 pac ...
- [Go语言]从Docker源码学习Go——if语句和map结构
if语句 继续看docker.go文件的main函数 if reexec.Init() { return } go语言的if不需要像其它语言那样必须加括号,而且,可以在判断以前,增加赋值语句 语法 I ...
- [Go语言]从Docker源码学习Go——init()方法和identifier首字母大小写区分
init()方法 如果想在一个go文件里,进行一些初始化的工作,可以把代码放到init()方法中. init()方法先被执行. func init() { // initialization of p ...
- [Go语言]从Docker源码学习Go——main函数
Go程序从main包下的main函数开始执行,当main执行结束后,程序退出. Docker的main函数在 docker/docker/docker.go package main //Import ...
- [Go语言]从Docker源码学习Go——Interfaces
Interface定义: type Namer interface { Method1(param_list) return_type Method2(param_list) return_type ...
- Go语言 context包源码学习
你必须非常努力,才能看起来毫不费力! 微信搜索公众号[ 漫漫Coding路 ],一起From Zero To Hero ! 前言 日常 Go 开发中,Context 包是用的最多的一个了,几乎所有函数 ...
- Docker源码分析(三):Docker Daemon启动
1 前言 Docker诞生以来,便引领了轻量级虚拟化容器领域的技术热潮.在这一潮流下,Google.IBM.Redhat等业界翘楚纷纷加入Docker阵营.虽然目前Docker仍然主要基于Linux平 ...
- Docker源码分析(二):Docker Client创建与命令执行
1. 前言 如今,Docker作为业界领先的轻量级虚拟化容器管理引擎,给全球开发者提供了一种新颖.便捷的软件集成测试与部署之道.在团队开发软件时,Docker可以提供可复用的运行环境.灵活的资源配置. ...
随机推荐
- 登录首页时报错:java.lang.IllegalArgumentException (不合法的参数异常)
处理一个老项目,DOWN下项目并配好之后,启动没问题,但是登陆之后首页显示如下: 控制台报错如下: 严重: Servlet.service() for servlet jsp threw except ...
- DDD~大话目录
来自:http://www.cnblogs.com/lori/p/3472789.html DDD~DDD从零起步架构说明 DDD~概念中的DDD DDD~microsoft NLayerApp项目中 ...
- sklearn 中模型保存的两种方法
一. sklearn中提供了高效的模型持久化模块joblib,将模型保存至硬盘. from sklearn.externals import joblib #lr是一个LogisticRegressi ...
- HIVE的transform函数的使用
Hive的TRANSFORM关键字提供了在SQL中调用自写脚本的功能,适合实现Hive中没有的功能又不想写UDF的情况.例如,按日期统计每天出现的uid数,通常用如下的SQL SELECT date, ...
- nginx-1.2.7 + tcp_proxy_module手动编译安装
Nginx开源软件默认没有提供TCP协议的负载均衡,下面记录一下我的安装过程: 1. 下载nginx最新稳定版的源码.可访问:http://www.nginx.org 或 linux命令下载到本地: ...
- 点滴积累【JS】---JQuery实现条形统计图,适用于选择题等统计
效果: 思路:前台JS实现动态数据效果,后台可以拼接字符串或者用JSON加载数据 代码: <%@ Page Language="C#" AutoEventWireup=&qu ...
- CCNA2.0笔记_OSPF v3
OSPF v3 是可以在ipv6上实现路由的一种路由协议 OSPF v2(for IPv4),OSPF v3(for IPv6)在一台路由器中互相独立运行 OSPF v3与v2有很多类似的功能: - ...
- vim插件管理器的安装和配置-windows
# vim插件管理器的安装和配置-windows ### 前言------------------------------ vim做一框功能强大的编辑器,扩展功能令人称奇,插件机制非常灵活- 本篇推荐 ...
- Solr学习01:Solr基础知识
一.什么是solr 首先,要了解下Solr是什么,以下是官方的描述. Solr是一个来自Apache Lucence项目,是一个热门开源的企业级搜索平台.为目前世界上相当多的大型互联网站点提供搜索和导 ...
- 查看网络连接数目(解决TIME_WAIT过多造成的问题_转)
转自:解决TIME_WAIT过多造成的问题 (eroswang的csdn) #netstat -n | awk '/^tcp/ {++S[$NF]} END { for(a in S) print ...