2015-04-22 61 views
3

我怎麼能通過結構功能作爲參數朗lang我怎樣才能通過結構功能作爲參數在朗lang

有我的代碼;

package main 

import (
    "fmt" 
) 

type MyClass struct { 
    Name string 
} 

func test(class interface{}) { 
    fmt.Println(class.Name) 
} 

func main() { 

    test(MyClass{Name: "Jhon"}) 
} 
當我運行它

,我得到這樣的錯誤

# command-line-arguments 
/tmp/sandbox290239038/main.go:12: class.Name undefined (type interface {} has no field or method Name) 

有play.google.com fiddle地址

回答

9

你要找的;

func test(class MyClass) { 
    fmt.Println(class.Name) 
} 

因爲它代表的方法識別class一些對象,實現了空接口(在該範圍意味着它的屬性和方法是完全未知的),這就是爲什麼你的錯誤。

你的其他選擇是這樣的;

func test(class interface{}) { 
    if c, ok := class.(MyClass); ok { // type assert on it  
     fmt.Println(c.Name) 
    } 
} 

但在你的例子中沒有理由。如果你打算做一個類型切換或者有多個代碼路徑根據class的實際類型做不同的事情,那麼它纔有意義。

+0

我試過你的第二個代碼片斷的結構,但我不能簡單地通過我的結構,當func需要接口{},那麼我如何通過func的正確論證? – Sir

3

根據您的需求,您有(至少)兩個選項:在結構類型

  • Func鍵

    1. 方法,它的結構類型作爲參數
    package main 
    
    import "fmt" 
    
    type MyClass struct { 
        Name string 
    } 
    
    func main() { 
        cls := MyClass{Name: "Jhon"} 
    
        // Both calls below produce same result 
        cls.StructMethod() // "Jhon" 
        FuncPassStruct(cls) // "Jhon" 
    } 
    
    // Method on struct type 
    func (class MyClass) StructMethod() { 
        fmt.Println(class.Name) 
    } 
    
    // Function that takes struct type as the parameter 
    func FuncPassStruct(class MyClass) { 
        fmt.Println(class.Name) 
    } 
    

    我相信其他人可能會提供一些我忘記的接口魔術。

  • 0

    請看看調試,收到方法。它使用stuct用戶及其方法。 https://play.golang.org/p/E_WkLWGdeB

    package main 
    
        import "fmt" 
    
        // user defines a user in the program. 
        type user struct { 
         name string 
         email string 
         status string 
        } 
        func debug(u user) { 
         fmt.Printf("%+v\n", u) 
        } 
    
        // notify implements a method with a value receiver. 
        func (u user) notify() { 
         fmt.Printf("User: Sending User Email To %s<%s>\n", u.name, u.email) 
        } 
    
        // changeEmail implements a method with a pointer receiver. 
        func (u *user) changeEmail(email string) { 
         u.email = email 
        } 
    
        func (u *user) changeName(name string) { 
         u.name = name 
        } 
    
        func (u *user) Send() { 
         u.notify() 
        } 
    
        // main is the entry point for the application. 
        func main() { 
         // Pointers of type user can also be used to methods 
         // declared with a value receiver. 
         john:= &user{"John", "[email protected]", "enabled"} 
    
         john.changeName("John Smith") 
         john.changeEmail("[email protected]") 
         john.notify() 
    
         Receive(john) 
    

    調試(用戶{ 「威利」, 「[email protected]」, 「啓用」})}

    func Receive(user interface{changeName(s string); changeEmail(s string); Send() }){ 
         user.changeName("Bill") 
         user.changeEmail("[email protected]") 
         user.Send() 
        } 
    
    0

    如果你真的想在發送的任何結構一般喜歡它是寫在你原來的問題(一個空的接口參數),以便AnyStruct.SomeField和AnotherStruct.SomeField或AnyOtherStruct.AnyField可以訪問,AFAIK go反射功能是要走的路。

    例如,如果您查看JSON編組函數,它幾乎可以接受任何結構作爲發送到具有空接口參數的函數的(「v」)參數。然後元帥函數結束調用

    e.reflectValue(reflect.ValueOf(v), opts) 
    

    但你可能尋找的東西簡單,因爲其他的答案都建議,這不會需要先進的反射(一種編程的通用方式)

    不過我發佈這個答案的情況下,其他讀者有興趣發送結構通常不需要知道結構字段是什麼。

    JSON解析器需要一般訪問結構的原因是爲了方便用戶定義他想要的任何結構,然後Go自動地計算出結構並將其映射到JSON語法。你可以想象100個不同的結構佈局,你只是想放在一個文本文件中,而不需要事先知道所有的結構佈局 - 函數可以在運行時找出它,這就是反射如何工作的(其他語言稱之爲運行時類型信息,元編程和類似)。