Nagaraja SV
Nagaraja SV

Reputation: 105

How to create a struct and its attributes dynamically using go code?

I am new to golang How to create a struct and attributes dynamically from gocode, it has to store it as a file in the end.

For example:

Struct name: user By default, it has to create Name attribute

type User struct {
    Name string
}

it has to store as a file ex: user_struct.go

Could you please someone help to find a way to do it

Upvotes: 0

Views: 538

Answers (2)

Adrian
Adrian

Reputation: 2113

If you are looking for ast based meta info about struct, receivers, etc you may consider the following:

package main
import  "github.com/viant/toolbox"

func main() {

    goCodeLocation := ".."
    fileSetInfo, err := toolbox.NewFileSetInfo(goCodeLocation)
    if err != nil {
        panic(err)
    }
    toolbox.Dump(fileSetInfo)
}

Upvotes: 0

Peter
Peter

Reputation: 31681

Use text/template to write Go code. Since I don't know how you want to do this in detail, I'll use a trivial template in the example. Any kind of real world template is bound produce ill-formated code, but thanks to go fmt you pretty much only have to get the newlines right (leverage semicolons if you ever have trouble with that). go fmt uses go/printer under the hood, and you can too.

See the linked package documentation and examples for details.

package main

import (
    "bytes"
    "go/parser"
    "go/printer"
    "go/token"
    "html/template"
    "io"
    "log"
    "os"
)

var structTpl = `
    package main

    type {{ . }} struct {
            Name string
    }
    `

func main() {
    // Only do this once per template at the start of your program.
    // Then simply call Execute as necessary.
    tpl := template.Must(template.New("foo").Parse(structTpl))

    messy := &bytes.Buffer{}
    tpl.Execute(messy, "User")

    // Parse the code
    fset := &token.FileSet{}
    ast, err := parser.ParseFile(fset, "", messy, parser.ParseComments|parser.DeclarationErrors)
    if err != nil {
        log.Fatal(err)
    }

    // Print the code, neatly formatted.
    neat := &bytes.Buffer{}
    err = printer.Fprint(neat, fset, ast)
    if err != nil {
        log.Fatal(err)
    }

    io.Copy(os.Stdout, neat) // Or write to file as desired.
}

Try it on the playground: https://play.golang.org/p/YhPAeos4-ek

Upvotes: 2

Related Questions