function和method关系

method是针对某一类型定义的function,

function可以单独调用,method必须针对某一类型的实例进行调用

//function 调用方式
packageName.FuncName() //method 调用方式
var t packageName.Type
t.MethodName()

源码

func (cli *DockerCli) LoadConfigFile() (err error) {
cli.configFile, err = registry.LoadConfig(os.Getenv("HOME"))
if err != nil {
fmt.Fprintf(cli.err, "WARNING: %s\n", err)
}
return err
} 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,
...
}
}

LoadConfigFile()是method,而NewDockerCli()是function。

Function

func functionName(parameter_list) (return_value_list) {
…
}
//parameter_list form (param1 type1, param2 type2, …)
//return_value_list form (ret1 type1, ret2 type2, …)

注:function可以返回多个参数,如果在调用时不想接受某个参数,使用下划线_

_, exist = FunctionName(...)

值/引用传递的问题

默认情况下,function中的参数是进行值传递的,如果想要在function内部修改原来数据的值,需要传递引用,用&符号。

例外:引用类型默认是进行引用传递的,比如slices, maps, interfaces, channels.

func ChangeValue(value *Struct1, newValue int) {
value.Int1 = newValue
} func NotChangeValue(value Struct1, newValue int) {
value2 := &value
value2.Int1 = newValue
}

可以通过定义最后一个参数的类型为...Type来传递多个同一类型的多个参数

func Min(ints ...int) int {
//ints类型为[]int{},值是传递进来的值。
if len(ints) == {
return -
}
min := ints[]
for _, x := range ints {
if x < min {
min = x
}
}
return min
} //调用
fmt.Println(Min(, , , , , ))
arr := []int{, , , , , }
fmt.Println(Min(arr...))

上面介绍的是传入多个相同类型的情况,那如果不同类型的多个怎么定义呢?

有两种方法,第一种是通过定义一个新的struct,包含这些不同的类型,然后把这个struct类型作为输入参数;第二种是使用空的Interface。

主要介绍第二种

func PrintType(variables ...interface{}) {
for _, v := range variables {
switch v.(type) {
case int:
fmt.Println("type is int %d", v)
default:
fmt.Println("other type %v", v)
}
}
} func showFunctionMultiInterfaceParameters() {
lemon.PrintType(, "aaaa")
var2 := []interface{}{, , , "bbb", "ccc"}
lemon.PrintType(var2...)
}

注:需要在方法内部判断类型,之后进行操作。

defer

defer用来定义在方法最后执行的语句,在return后,}之前。

注意:在同一个方法中先后定义两个defer,执行顺序是倒序的,LIFO.

func DeferOrder() {
for i := ; i < ; i++ {
defer fmt.Println("index value is %d", i)
}
}
//输出
index value is %d
index value is %d
index value is %d
index value is %d

method

method是特殊的function,定义在某一特定的类型上,通过类型的实例来进行调用,这个实例被叫receiver。

receiver类型可以是任意类型,包括function类型,但是,receiver不能是interface类型。

func (recv receiver_type) methodName(parameter_list) (return_value_list) {...}

注:method和它的类型必须定义在一个包内!但是我们可以通过其它的方式来实现。

解决思路:怎么样可以让原来的类型在我们自己的包中定义呢?

两种方法:

第一种,通过alias。

type Int int

这样在对Int进行方法定义。

第二种,通过匿名属性

type Int struct{
int
}

两种方法,第二种比较好,因为第一种只针对当前的alias有用,重用性不如第二种方法好。

如果想要在method内部修改receiver的属性值,recv *receiver_type(在type前面增加一个*),表示传入引用。

此时传入值也没关系,go语言自动实现转化,t.Func转换为(&t).Func.

func (b *B) change(){...}

var b1 B
b1.change()

总结

go语言中把method和type分开进行定义。

好处是我们可以为任何类型增加方法,而不用去修改原来的代码。

[Go语言]从Docker源码学习Go——function和method的更多相关文章

  1. [Go语言]从Docker源码学习Go——结构和函数的定义

    Docker在最近很火,而作为Docker的开发语言-Go也再次被大家提到. 已经使用Docker一段时间了,但是对于源码,尤其是其开发语言Go却一直是一知半解. 最近准备利用空余时间从Docker源 ...

  2. [Go语言]从Docker源码学习Go——指针和Structs

    这两天在看reflect这个包在Docker中的使用时,遇到了各种问题,最后虽然知道怎么用了. 但是对于这块的原理还不是太懂,于是把"THE WAY TO GO"中关键的几章看了下 ...

  3. [Go语言]从Docker源码学习Go——if语句和map结构

    if语句 继续看docker.go文件的main函数 if reexec.Init() { return } go语言的if不需要像其它语言那样必须加括号,而且,可以在判断以前,增加赋值语句 语法 I ...

  4. [Go语言]从Docker源码学习Go——init()方法和identifier首字母大小写区分

    init()方法 如果想在一个go文件里,进行一些初始化的工作,可以把代码放到init()方法中. init()方法先被执行. func init() { // initialization of p ...

  5. [Go语言]从Docker源码学习Go——main函数

    Go程序从main包下的main函数开始执行,当main执行结束后,程序退出. Docker的main函数在 docker/docker/docker.go package main //Import ...

  6. [Go语言]从Docker源码学习Go——Interfaces

    Interface定义: type Namer interface { Method1(param_list) return_type Method2(param_list) return_type ...

  7. Go语言 context包源码学习

    你必须非常努力,才能看起来毫不费力! 微信搜索公众号[ 漫漫Coding路 ],一起From Zero To Hero ! 前言 日常 Go 开发中,Context 包是用的最多的一个了,几乎所有函数 ...

  8. Docker源码分析(三):Docker Daemon启动

    1 前言 Docker诞生以来,便引领了轻量级虚拟化容器领域的技术热潮.在这一潮流下,Google.IBM.Redhat等业界翘楚纷纷加入Docker阵营.虽然目前Docker仍然主要基于Linux平 ...

  9. Docker源码分析(二):Docker Client创建与命令执行

    1. 前言 如今,Docker作为业界领先的轻量级虚拟化容器管理引擎,给全球开发者提供了一种新颖.便捷的软件集成测试与部署之道.在团队开发软件时,Docker可以提供可复用的运行环境.灵活的资源配置. ...

随机推荐

  1. Qt-优化布局结构

    在迄今为止讲到每一个例子中,我们只是简单的把窗口部件放置到某个确定的布局中.但在某些情况下,由此形成的布局看起来可能还不是我们最想要的形式.在这些情形中,可以通过改变要摆放的窗口部件的大小策略和大小提 ...

  2. kettle--组件(3)--行转列

    组件图如下: 以上操作可以这么理解: IF(DATA1=DATA4) THEN DATA2=DATA3 也就是关键字值的数值会与关键字段的数值匹配,匹配上了就显示数据value filedname所填 ...

  3. NFC Basics(基本NFC)——翻译自developer.android.com

    NFC Basics 关于收发NDEF格式的消息,以及相关的api. 非NDEFdata以及其它更深入技术请參见Advanced NFC. 在android端使用NDEF有两种情况: - 从标签读取N ...

  4. .Net MVC ViewBag

    ViewBag用来做视图的值绑定,我不清楚是不是这么称呼.之前看过安卓的值绑定做法,mvc直接动态类型,瞬间逼格满满 Controller: public class HomeController : ...

  5. 所需即所获:像 IDE 一样使用 vim

    所需即所获:像 IDE 一样使用 vim 转载 yangyangwithgnu@yeah.net2015-11-08 10:05:53 谢谢 捐赠:支付宝 yangyangwithgnu@yeah.n ...

  6. 3.selenium模块

    本节内容: 介绍 安装 基本使用 选择器 等待元素被加载 元素交互操作 其他 项目练习 一.介绍 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行Ja ...

  7. 李洪强和你一起学习前端之(7)定位盒子 css可见性 滑动门案例

    今天是2017年3月23日 1 复习昨天知识 1.1浮动 Float:left | right 特点: ->浮动的元素不占位置(脱标) ->可以将行内元素转化为行内块元素 ->块级元 ...

  8. c# 字符串排序 (面试题)

    将一些字符串,如: "bc", "ad", "ac", "hello", "xman", " ...

  9. Spark Standalone与Spark on YARN的几种提交方式

    不多说,直接上干货! Spark Standalone的几种提交方式 别忘了先启动spark集群!!! spark-shell用于调试,spark-submit用于生产. 1.spark-shell ...

  10. Unix系统编程()通用模型以外的操作ioctl

    之前学习到的都是通用的IO模型,现在要学的是一个ioctl系统调用,ioctl为执行文件和设备提供了一种多用途机制. int ioctl(int fd, int request, - /*argp*/ ...