title: How to make a generic form function for froms with interfeces with gin (framework) and golang?
body: <p>I want to create a function to process anykind of forms.
  I want it to be able to handle any kind of data types.
  Im trying to use a interface to do this task.</p>
  
  <pre><code>type Person struct {
      name        string 
      lastName    string
  }
  
  
  func HTMLForm(c *gin.Context) {
      var f Person
      c.ShouldBind(&amp;f)
      c.JSON(http.StatusOK, f)
  }
  
  // with this function i get the correct info
  
  // output: {"name":"john","lastName":"snow"}
  
  func HTMLForm(c *gin.Context) {
      var f interface{}
      c.ShouldBind(&amp;f)
      c.JSON(http.StatusOK, f)
  }
  
  // when i use the interface to make it usefull for any type of that
  // i get null
  
  // output: null
  
  func HTMLForm(c *gin.Context) {
      var f interface{}
      ShouldBindJSON(f)
      c.JSON(http.StatusOK, f)
  }
  
  // output: null
  </code></pre>
  
  <p>I want to get, with the interface, the same output I get with "Person" data type.</p>
  
  <pre><code>// Another example of how i am using f
  
  type Login struct {
      User     string 
      Password string 
  }
  
  func main() {
      router := gin.Default()
  
      router.POST("/loginForm", func(c *gin.Context) {
          var f interface{}
  
          if err := c.ShouldBind(&amp;f); err != nil {
              c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
              return
          }
  
          c.JSON(http.StatusOK, f)
      })
  
      // Listen and serve on 0.0.0.0:8080
      router.Run(":8080")
  }
  
  // output: null
  </code></pre>
  
  <p>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  Update</p>
  
  <p>I want to try to explain my problem better.
  Maybe this update it's more clear.</p>
  
  <pre><code>// Golang code
  package main
  
  import (
      "net/http"
  
      "github.com/gin-gonic/gin"
  )
  
  // Binding from JSON
  type Login struct {
      User     string `form:"user" json:"user" xml:"user"  binding:"required"`
      Password string `form:"password" json:"password" xml:"password" binding:"required"`
  }
  
  func main() {
      router := gin.Default()
  
      router.LoadHTMLGlob("templates/*")
  
      router.GET("/login", GetLogin)
      router.POST("/loginJSON", PostJSONForm)
      router.POST("/loginXML", PostXMLForm)
      router.POST("/loginForm", PostHTMLForm)
  
      /*
          sudo lsof -n -i :8080
          kill -9 &lt;PID&gt;
      */
      router.Run(":8080")
  }
  
  func GetLogin(c *gin.Context) {
      c.HTML(http.StatusOK, "login.tmpl", nil)
  }
  
  // Example for binding JSON ({"user": "manu", "password": "123"})
  // curl -v -X POST http://localhost:8080/loginJSON -H 'content-type: application/json' '{ "user": "manu", "password"="123" }'
  func PostJSONForm(c *gin.Context) {
      //var json Login
      var json interface{}
      //var form map[string]interface{}
  
      if err := c.ShouldBindJSON(&amp;json); err != nil {
          c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
          return
      }
  
      /*
          if json.User != "manu" || json.Password != "123" {
              c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
              return
          }
          c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
      */
  
      c.JSON(http.StatusOK, "json")
      c.JSON(http.StatusOK, json)
  }
  
  // Example for binding XML (
  //  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  //  &lt;root&gt;
  //      &lt;user&gt;user&lt;/user&gt;
  //      &lt;password&gt;123&lt;/password&gt;
  //  &lt;/root&gt;)
  // curl -v -X POST http://localhost:8080/loginXML -H 'content-type: application/json' -d '{ "user": "manu", "password"="123" }'
  func PostXMLForm(c *gin.Context) {
      //var xml Login
      var xml interface{}
      //var form map[string]interface{}
  
      if err := c.ShouldBindXML(&amp;xml); err != nil {
          c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
          return
      }
  
      /*
          if xml.User != "manu" || xml.Password != "123" {
              c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
              return
          }
          c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
      */
  
      c.JSON(http.StatusOK, "xml")
      c.JSON(http.StatusOK, xml)
  }
  
  // Example for binding a HTML form (user=manu&amp;password=123)
  // curl -v -X POST http://localhost:8080/loginForm -H 'content-type: application/json' -d '{ "user": "manu", "password":"123" }'
  func PostHTMLForm(c *gin.Context) {
      //var form Login
      var form interface{}
      //var form map[string]interface{}
  
      // This will infer what binder to use depending on the content-type header.
      if err := c.ShouldBind(&amp;form); err != nil {
          c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
          return
      }
  
      /*
          if form.User != "manu" || form.Password != "123" {
              c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
              return
          }
          c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
      */
  
      c.JSON(http.StatusOK, "html")
      c.JSON(http.StatusOK, form)
  }
  
  //Template
  &lt;h1&gt;Login&lt;/h1&gt;
  &lt;form action="/loginForm" method="POST"&gt;
      &lt;label&gt;user:&lt;/label&gt;&lt;br&gt;
      &lt;input type="text" name="user"&gt;&lt;br&gt;
  
      &lt;label&gt;password:&lt;/label&gt;&lt;br&gt;
      &lt;input type="text" name="password"&gt;&lt;br&gt;
  
      &lt;input type="submit"&gt;
  &lt;/form&gt;
  </code></pre>
  
  <ol>
  <li><p>I have tried all this different variations. Just one works, I explain more below.</p></li>
  <li><p>It works perfect if I use "var form Login" instead of "var from interface{}". But I need it to be able to work with any data type, so I need it to work with interface{}.</p></li>
  <li><p>I have had a "successful" output, just with one of interface{} tries:</p></li>
  </ol>
  
  <p>$ curl -X POST <a href="http://localhost:8080/loginForm" rel="nofollow noreferrer">http://localhost:8080/loginForm</a> -H 'content-type: application/json' -d '{ "user": "manu", "password":"123" }'</p>
  
  <p>output:"html"{"password":"123","user":"manu"}</p>
  
  <ol start="4">
  <li>But when I use it on a HTML form, on a browser, with that template I posted i get:</li>
  </ol>
  
  <p>output: "html"null</p>
  
  <ol start="5">
  <li>Im not sure if what I get (point 3) its really a sucessfull output. When I use the Login var, it works fine, with curl and brower, the output it's inverted:</li>
  </ol>
  
  <p>$  curl -X POST <a href="http://localhost:8080/loginForm" rel="nofollow noreferrer">http://localhost:8080/loginForm</a> -H 'content-type: application/json' -d '{ "user": "manu", "password":"123" }'</p>
  
  <p>ouput:"html"{"user":"manu","password":"123"}</p>
  
  <p>This is all information I could get till now.</p>