zoukankan      html  css  js  c++  java
  • golang Methods on structs

    原文:http://golangtutorials.blogspot.com/2011/06/methods-on-structs.html

    snmp 下载,有空学习一下!

    https://sourceforge.net/projects/net-snmp/

    --------------------------------------------------------------------------------------------------------

    Methods on structs

     

    We have learnt that structs can contain data. structs can also contain behavior in the form of methods. The definition of a method attached to or associated with a struct or any other type for that matter, is quite similar to a normal func definition, the only difference being that you need to additionally specify the type.

    A normal function that we name my_func that takes no parameters and returns an int would be defined similar to that shown below.

    Partial code
    func my_func() int {
       //code
    }
    

    A function or method that we name my_func that takes no parameters and returns an int, but which is associated with a type we name my_type would be defined similar to that shown below.

    Partial code
    type my_type struct { }
    
    func (m my_type) my_func() int {
       //code
    }
    

    Let’s extend our earlier Rectangle struct to add an Area function. This time we will define that the Area function works explicitly with the Rectangle type with func (r Rectangle) Area() int.

    Full code
    package main
    
    import "fmt"
    
    type Rectangle struct {
        length, width int
    }
    
    func (r Rectangle) Area() int {
        return r.length * r.width
    }
    
    func main() {
        r1 := Rectangle{4, 3}
        fmt.Println("Rectangle is: ", r1)
        fmt.Println("Rectangle area is: ", r1.Area())
    }
    

    Rectangle is: {4 3}
    Rectangle area is: 12

    Many object oriented languages have a concept of this or self that implicitly refers to the current instance. Go has no such keyword. When defining a function or method associated with a type, it is given as a named variable - in this case (r Rectangle) and then within the function the variable r is used.

    In the above call to Area, the instance of Rectangle is passed as a value. You could also pass it by reference. In calling the function, there would be no difference whether the instance that you call it with is a pointer or a value because Go will automatically do the conversion for you.

    Full code
    package main
    
    import "fmt"
    
    type Rectangle struct {
        length, width int
    }
    
    func (r Rectangle) Area_by_value() int {
        return r.length * r.width
    }
    
    func (r *Rectangle) Area_by_reference() int {
        return r.length * r.width
    }
    
    func main() {
        r1 := Rectangle{4, 3}
        fmt.Println("Rectangle is: ", r1)
        fmt.Println("Rectangle area is: ", r1.Area_by_value())
        fmt.Println("Rectangle area is: ", r1.Area_by_reference())
        fmt.Println("Rectangle area is: ", (&r1).Area_by_value())
        fmt.Println("Rectangle area is: ", (&r1).Area_by_reference())
    }
    

    Rectangle is: {4 3}
    Rectangle area is: 12
    Rectangle area is: 12
    Rectangle area is: 12
    Rectangle area is: 12

    In the above code, we have defined two similar functions, one which takes the Rectangle instance as a pointer and one that takes it by value. We have called each of the functions, via a value r1 and once as an address &r1. The results however are all the same since Go performs appropriate conversions.

    Just to extend the example, let’s do one more function that works on the same type. In the below example, we ‘attach’ a function to calculate the perimeter of the Rectangle type.

    Full code
    package main
    
    import "fmt"
    
    type Rectangle struct {
        length, width int
    }
    
    func (r Rectangle) Area() int {
        return r.length * r.width
    }
    
    func (r Rectangle) Perimeter() int {
        return 2* (r.length + r.width)
    }
    
    func main() {
        r1 := Rectangle{4, 3}
        fmt.Println("Rectangle is: ", r1)
        fmt.Println("Rectangle area is: ", r1.Area())
        fmt.Println("Rectangle perimeter is: ", r1.Perimeter())
    }
    

    Rectangle is: {4 3}
    Rectangle area is: 12
    Rectangle perimeter is: 14

    You might be tempted now to see if you can attach methods and behavior to any type, say like an int or time.Time - not possible. You will be able to add methods for a type only if the type is defined in the same package.

    Partial code
    func (t time.Time) first5Chars() string {
        return time.LocalTime().String()[0:5]
    }
    

    cannot define new methods on non-local type time.Time

    However, if you absolutely need to extend the functionality, you can easily use what we learnt about anonymous fields and extend the functionality.

    Full code
    package main
    
    import "fmt"
    import "time"
    
    type myTime struct {
        time.Time //anonymous field
    }
    
    func (t myTime) first5Chars() string {
        return t.Time.String()[0:5]
    }
    
    func main() {
        m := myTime{*time.LocalTime()} //since time.LocalTime returns an address, we convert it to a value with *
      // m := myTime{time.Now()}  这行是对的!!!!!!!!!! fmt.Println("Full time now:", m.String()) //calling existing String method on anonymous Time field fmt.Println("First 5 chars:", m.first5Chars()) //calling myTime.first5Chars }

    Full time now: Tue Nov 10 23:00:00 UTC 2009
    First 5 chars: Tue N


    Methods on anonymous fields

    There was another item that we slipped into the previous program - method calls on anonymous fields. Since time.Time was an anonymous field within myTime, we were able to refer to a method of Time as if it were a method of myTime. i.e. we were able to do myTime.String(). Let’s do one program using an earlier example.

    In the following code we go back to our house where we have a Kitchen as an anonymous field in House. As we learnt with member fields, we can also access methods of anonymous fields as if they belong directly to the composing type. So House has an anonymous Kitchen which in turn has a method totalForksAndKnives(); so now House.totalForksAndKnives() is a valid call.

    Full code
    package main
    
    import "fmt"
    
    type Kitchen struct {
        numOfForks int 
        numOfKnives int
    }
    
    func(k Kitchen) totalForksAndKnives() int {
        return k.numOfForks + k.numOfKnives
    }
    
    type House struct {
        Kitchen //anonymous field
    }
    
    func main() {
        h := House{Kitchen{4, 4}} //the kitchen has 4 forks and 4 knives
        fmt.Println("Sum of forks and knives in house: ", h.totalForksAndKnives())  //called on House even though the method is associated with Kitchen
    }
    

    Sum of forks and knives in house: 8
  • 相关阅读:
    通过system调用Am命令执行动作
    windows中如何在命令行启动启动程序
    UICC 实现框架和数据读写
    软件设计方法(转载)
    好诗欣赏——邀请 The Invitation
    leaflet使用turfjs插件,基于格点数据绘制等值线效果
    深信服防火墙做端口映射
    关于本博客的一些声明
    sqlserver – SQL Server – 包含多个字段的IN子句
    JavaScript Array join() 方法
  • 原文地址:https://www.cnblogs.com/oxspirt/p/11650723.html
Copyright © 2011-2022 走看看