设为首页 收藏本站
查看: 1315|回复: 0

[经验分享] [Go语言]从Docker源码学习Go——function和method

[复制链接]

尚未签到

发表于 2015-4-18 05:30:18 | 显示全部楼层 |阅读模式
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) == 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。
  主要介绍第二种



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.



func DeferOrder() {
for i := 0; i < 4; i++ {
defer fmt.Println("index value is %d", i)
}
}
//输出
index value is %d 3
index value is %d 2
index value is %d 1
index value is %d 0
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分开进行定义。
  好处是我们可以为任何类型增加方法,而不用去修改原来的代码。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58158-1-1.html 上篇帖子: docker level2 下篇帖子: 深入浅出Docker(二):Docker命令行探秘
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表