Messing up templates


(Kumar Abhishek) #1

I am trying to push multiple variables into my Html template but unable to do that.
The template is as below
<html>

&lt;head&gt;

&lt;title&gt;Current IP Check&lt;/title&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;div&gt;Current IP Address: {{.injectIP}}&lt;/div&gt;

&lt;div&gt;Current Location: {{.injectCity}}&lt;/div&gt;

&lt;/body&gt;

&lt;/html&gt;

the go file is this
package main

// modules requirement.
import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

type Htmltemp struct {
	injectIP   string
	injectCity string
}

// template to parse the json and pass to html
type Geo struct {
	City string `json:"city"`
}

// Main function, to create a web server on port 80
func main() {

	http.HandleFunc("/", ReadUserIP)
	http.ListenAndServe(":80", nil)
}

func ReadUserIP(w http.ResponseWriter, r *http.Request) {

	//check for X-forwarded-for Header
	IPAddress := ""
	if IPAddress == "" {
		//IPAddress = r.Header.Get("x-forwarded-for")
		IPAddress = "134.201.250.155, 23:24:3:5" // -----------to be deleted hardcoded for testing
	}
	// print the remote address from request
	if IPAddress == "" {
		IPAddress = r.RemoteAddr
	}
	// iterrate the string for desired value.

	ipadd := strings.Split(IPAddress, ",") //---- my change from : to ,
	cip1 := ipadd[0]
	//t.Execute(w, cip1)

	// creating the endpoint for Geolocation API call, by inserting the located IP
	buffer := bytes.Buffer{}
	buffer.WriteString("http://api.ipstack.com/")
	buffer.WriteString(cip1)
	buffer.WriteString("?access_key=2dd2ca2a9f39638d4f61533ecb1b337b&fields=city") //please register at the site and get a new key I changed my key, also  - buy paid version for getting Timezone data using this API
	url := buffer.String()

	// making the API call to recieve the IP related data
	response, err := http.Get(url)
	if err != nil {
		fmt.Print(err.Error())
		os.Exit(1)
	}
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Fatal(err)
	}
	//fmt.Println(string(responseData)) // for viewing the response

	//parsing of Json and insertion of location and timezone in output file "t" is pending
	// - unmarshalling the json
	// then inserting them in the html template
	var geo Geo

	err = json.Unmarshal(responseData, &geo)
	if err != nil {
		panic(err)
	}
	fmt.Println(geo.City)

	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	t, err := template.ParseFiles("index.html")
	if err != nil {
		fmt.Fprintf(w, "Unable to load template")
	}
	inject := Htmltemp{injectIP: cip1, injectCity: geo.City}
	t.Execute(w, inject)

}

(Norbert Melzer) #2

What is the error that you see? If you don’t see one, please make sure to not ignore the result of t.Execute(…).


PS and edit:

I went through the hassle to run your code on my end and printing the result of t.Execuite(…):

template: index.html:9:33: executing "index.html" at <.injectIP>: injectIP is an unexported field of struct type main.Htmltemp

As templates are rendered using reflection, all fields refered to in the template itself needs to be exported from the context. You can not use private fields in the template.


(Kumar Abhishek) #3

I had tried exporting them as you can see

type Htmltemp struct {
	injectIP   string
	injectCity string
}

This is simply magical the only thing I changed is Made the starting case of the below fields in my code , it is working perfectly now

&lt;div&gt;Current IP Address: {{.InjectIP}}&lt;/div&gt;
&lt;div&gt;Current Location: {{.InjectCity}}&lt;/div&gt;

and also changed in the exported template in the go program

type Htmltemp struct {
	InjectIP   string
	InjectCity string
}

Is it something of a requirement that exported variables must be starting in CAPS ??


(Norbert Melzer) #4

Yes, identifiers starting with a capital letter are exposed from the package, lower cased are not and only available internally.

Its covered in the tour even before you have written any meaningful code:

https://tour.golang.org/basics/3


(Kumar Abhishek) #5

Thanks this was my first crash and burn Hello World kind of program in GO. Just to get motivated. Have started on the Tutorials now. I am surprised that the code volume appears very less in GO for achieving relatively complex task. Its superb