How can I pass a struct to a function as parameter?

go
75,175

Solution 1

You're looking for;

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

As it stands the method recognizes class as some object which implements the empty interface (meaning in that scope it's fields and methods are completely unknown) which is why you get the error.

Your other option is something like this;

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

But there is no reason to in your example. It only makes sense if you're going to do a type switch or have multiple code paths that do different things based on the actual type of class.

Solution 2

Depending on your needs, you have (at least) two options:

  1. Method on the struct type
  2. Func that takes struct type as parameter
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)
}

I'm sure others may provide some interface wizardry I'm forgetting.

Solution 3

If you really want to send any struct in generically like it is written in your original question (an empty interface parameter) so that AnyStruct.SomeField and AnotherStruct.SomeField, or AnyOtherStruct.AnyField can be accessed, AFAIK the reflecton features of go are the way to go.

For example if you look at the JSON marshal function it accepts pretty much any struct as a ("v") parameter sent in to a function with an empty interface parameter. Then that marshal function ends up calling

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

But you are probably looking for something simple as the other answers have suggested, which would not need advanced reflection (a sort of generic way of programming)

However I post this answer in case other readers are interested in sending structs in generally without needing to know up front what the struct fields are.

The reason a JSON parser needs to generically access a struct is for convenience of the user defining any struct he wants, and then Go automagically figures out the struct and maps it to a JSON syntax. You could imagine 100's of different struct layouts that you just want to place into a text file, without knowing all your struct layouts upfront - the function can figure out it at run time, which is how reflection works (other languages call it run time type information, meta programming, and similar).

Solution 4

Please take a look over the Debug ,Receive methods. It uses stuct user, with its methods. 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)
    debug(user{"Willy", "[email protected]", "enabled"})
}

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


Share:
75,175

Related videos on Youtube

alioygur
Author by

alioygur

Updated on July 09, 2022

Comments

  • alioygur
    alioygur almost 2 years

    How can I pass a struct to function as a parameter in golang? There is my code:

    package main
    
    import (
        "fmt"
    )
    
    type MyClass struct {
        Name string
    }
    
    func test(class interface{}) {
        fmt.Println(class.Name)
    }
    
    func main() {
    
        test(MyClass{Name: "Jhon"})
    }
    

    when I run it, I am getting an error like this

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

    there is play.golang.org fiddle address.

  • Sir
    Sir over 6 years
    I tried your second code snippet for a struct but i can't simply pass my struct in when the func takes interface{} so how do i pass a correct arguement for the func ?
  • Angger
    Angger about 6 years
    can we do this without asserting? so its receive dynamic struct.
  • evanmcdonnal
    evanmcdonnal about 6 years
    @Angger you don't have to do the type assertion, if you know what methods the interface offers you can just call one. The type assertion would be used if the method set provided by incoming types differs and you need to do something specific based on which type is passed in.
  • Amulya Kashyap
    Amulya Kashyap almost 6 years
    Now additionally I want to add interface which keeps list of all functions/Methods. How would we implement that ?
  • openwonk
    openwonk almost 6 years
    Can you elaborate more @AmulyaKashyap? Describe what your aiming to do.
  • Meghan
    Meghan about 4 years
    TIL you can grab the ok 2nd arg out of a type assertion. Thanks for this :D