前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Go语言]从Docker源码学习Go——指针和Structs - lemon_bar

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

作者头像
李海彬
发布2018-03-20 10:38:25
7300
发布2018-03-20 10:38:25
举报
文章被收录于专栏:Golang语言社区

http://www.cnblogs.com/lemonbar/p/3932981.html

主题 Go语言 Docker

function和method关系

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

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

代码语言:javascript
复制
//function 调用方式packageName.FuncName()//method 调用方式var t packageName.Type
t.MethodName()

源码

代码语言:javascript
复制
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

代码语言:javascript
复制
func functionName(parameter_list) (return_value_list) {
…
}//parameter_list form (param1 type1, param2 type2, …)//return_value_list form (ret1 type1, ret2 type2, …)

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

代码语言:javascript
复制
_, exist = FunctionName(...)

值/引用传递的问题

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

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

代码语言:javascript
复制
func ChangeValue(value *Struct1, newValue int) {  value.Int1 = newValue
}

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

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

代码语言:javascript
复制
func Min(ints ...int) int {//ints类型为[]int{},值是传递进来的值。  if len(ints) == 0 {    return -1  }  min := ints[0]  for _, x := range ints {    if x < min {      min = x    }  }  return min
}//调用fmt.Println(Min(4, 6, 9, 10, 3, 2))
arr := []int{9, 5, 3, 10, 20, 2}
fmt.Println(Min(arr...))

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

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

主要介绍第二种

代码语言:javascript
复制
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(5, "aaaa")  var2 := []interface{}{6, 7, 9, "bbb", "ccc"}  lemon.PrintType(var2...)
}

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

defer

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

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

代码语言:javascript
复制
func DeferOrder() {  for i := 0; i < 4; i++ {    defer fmt.Println("index value is %d", i)  }
}//输出index value is %d 3index value is %d 2index value is %d 1index value is %d 0

method

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

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

代码语言:javascript
复制
func (recv receiver_type) methodName(parameter_list) (return_value_list) {...}

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

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

两种方法:

第一种,通过alias。

代码语言:javascript
复制
type Int int

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

第二种,通过匿名属性

代码语言:javascript
复制
type Int struct{    int}

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

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

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

代码语言:javascript
复制
func (b *B) change(){...}var b1 B
b1.change()

总结

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-02-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • function和method关系
  • 源码
  • Function
    • 值/引用传递的问题
      • defer
      • method
      • 总结
      相关产品与服务
      容器镜像服务
      容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档