Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass data struct as parameter in golang

Tags:

go

XML to Json

package main

import (
    "encoding/json"
    "encoding/xml"
    "fmt"
)

type Persons struct {
    Person []struct {
        Name string
        Age  int
    }
}
type Places struct {
    Place []struct {
        Name    string
        Country string
    }
}

type Parks struct {
    Park struct {
        Name     []string
        Capacity []int
    }
}

const personXml = `
    <Persons>
        <Person><Name>Koti</Name><Age>30</Age></Person>
        <Person><Name>Kanna</Name><Age>29</Age></Person>
    </Persons>
`

const placeXml = `
    <Places>
        <Place><Name>Chennai</Name><Country>India</Country></Place>
        <Place><Name>London</Name><Country>UK</Country></Place>
    </Places>
`

const parkXml = `
    <Parks>
        <Park><Name>National Park</Name><Capacity>10000</Capacity></Park>
        <Park>Asian Park</Name><Capacity>20000</Capacity></Park>
    </Parks>
`

func WhatIamUsing() {
    var persons Persons
    xml.Unmarshal([]byte(personXml), &persons)
    per, _ := json.Marshal(persons)
    fmt.Printf("%s\n", per)

    var places Places
    xml.Unmarshal([]byte(placeXml), &places)
    pla, _ := json.Marshal(places)
    fmt.Printf("%s\n", pla)

    var parks Parks
    xml.Unmarshal([]byte(parkXml), &parks)
    par, _ := json.Marshal(parks)
    fmt.Printf("%s\n", par)
}

What i want is a generic function which takes xml string and dataStruct and returns a Json output. But below function is throwing an error How to impliment this?

func Xml2Json(xmlString string, DataStruct interface{}) (jsobj string, err error) {
    var dataStruct DataStruct
    xml.Unmarshal([]byte(personXml), &dataStruct)
    js, _ := json.Marshal(dataStruct)
    return fmt.Sprintf("%s\n", js), nil
}

func main() {
    jsonstring, _ := Xml2Json(personXml, Persons)
}

Error message:

prog.go:73: DataStruct is not a type

prog.go:80: type Persons is not an expression

goplay link: http://play.golang.org/p/vayb0bawKx

like image 470
ekanna Avatar asked Aug 15 '13 08:08

ekanna


People also ask

How do you declare a struct in Golang?

Each data field in a struct is declared with a known type, which could be a built-in type or another user-defined type. Structs are the only way to create concrete user-defined types in Golang. Struct types are declared by composing a fixed set of unique fields.

What is pass by reference and pass by value in Golang?

And pass by reference is when we pass the parameter with a pointer to the given parameter. In Golang, we can see these two in this example below. Actually, there are already many examples of how to do pass by reference and pass by value in Golang that we can find on the Internet.

How to create a greetable in Golang?

One solution would be to create an interface and a greeting method. type Greetable interface { Greeting () string Name () string } You would then implement the Greeting and Name methods in your struct (this would immediately implement the Greetable interface, due to the way that Go handles interfaces ):

How to do something inside an interface in Golang?

There is a generic function that will accept interface {} and do something inside it. And it supports many structs. The snippet code would be like this: This one is really-really a serious thing in Golang. We must very careful when working with pass-by-reference and interface {}.


2 Answers

You can not store a type (like Persons) in an interface. You could pass a reflect.Type to your function. Then, your call would look like Xml2Json(personXml, reflect.TypeOf(Persons)) which is quite ugly in my opinion.

The better approach is probably:

func Xml2Json(xmlString string, value interface{}) (string, error) {
    if err := xml.Unmarshal([]byte(xmlString), value); err != nil {
        return "", err
    }
    js, err := json.Marshal(value)
    if err != nil {
        return "", err
    }
    return string(js), nil
}

You can use this function with Xml2Json(personXml, new(Persons)) if you are not interested in the value itself, and

var persons Persons
Xml2Json(personXML, &persons)

when you also want to retrieve the struct value for later processing.

like image 123
tux21b Avatar answered Oct 01 '22 14:10

tux21b


The function Xml2Json declares a parameter named DataStruct. In the same scope the identifier DataStruct cannot denote a type name. If you want to use the type name DataStruct within the same scope, you must name your parameter differently.

In the main function the problem is that a function call syntax expects an expression list within the parenthesis. There you're passing a type name, which clearly cannot be an expression.

So to answer your question: No, you cannot pass a type as an argument to a function. But you can pass an instance of a type (in this case a pointer to such instance) to get the effect you're about:

package main

import (
        "encoding/json"
        "encoding/xml"
        "fmt"
        "log"
)

type Persons struct {
        Person []struct {
                Name string
                Age  int
        }
}

type Places struct {
        Place []struct {
                Name    string
                Country string
        }
}

type Parks struct {
        Park struct {
                Name     []string
                Capacity []int
        }
}

const (
        personXml = `
    <Persons>
        <Person><Name>Koti</Name><Age>30</Age></Person>
        <Person><Name>Kanna</Name><Age>29</Age></Person>
    </Persons>
`
        placeXml = `
    <Places>
        <Place><Name>Chennai</Name><Country>India</Country></Place>
        <Place><Name>London</Name><Country>UK</Country></Place>
    </Places>
`

        parkXml = `
    <Parks>
        <Park><Name>National Park</Name><Capacity>10000</Capacity></Park>
        <Park><Name>Asian Park</Name><Capacity>20000</Capacity></Park>
    </Parks>
`
)

func Xml2Json(xmlString string, DataStruct interface{}) (jsobj string, err error) {
        if err = xml.Unmarshal([]byte(xmlString), DataStruct); err != nil {
                return
        }

        js, err := json.Marshal(DataStruct)
        if err != nil {
                return
        }

        return fmt.Sprintf("%s", js), nil
}

func main() {
        var p Persons
        jsonstring, err := Xml2Json(personXml, &p)
        if err != nil {
                log.Fatal(err)
        }

        fmt.Println(jsonstring)

        var q Places
        jsonstring, err = Xml2Json(placeXml, &q)
        if err != nil {
                log.Fatal(err)
        }

        fmt.Println(jsonstring)

        var r Parks
        jsonstring, err = Xml2Json(parkXml, &r)
        if err != nil {
                log.Fatal(err)
        }

        fmt.Println(jsonstring)

}

Playground


Output:

{"Person":[{"Name":"Koti","Age":30},{"Name":"Kanna","Age":29}]}
{"Place":[{"Name":"Chennai","Country":"India"},{"Name":"London","Country":"UK"}]}
{"Park":{"Name":["National Park","Asian Park"],"Capacity":[10000,20000]}}
like image 31
zzzz Avatar answered Oct 01 '22 14:10

zzzz