I ran into a problem in golang the other day where my bytes.Buffer wasn't storing the bytes I was writing to it. Turns out it's a simple misunderstanding of golang pointers vs golang values.
I had a struct with a single byte.Buffer in it.
type HtmlRewriter struct {
buf bytes.Buffer
}
func (w HtmlRewriter) Write(p []byte) (n int, err error) {
return w.buf.Write(p)
}
It's a simple struct which implements the io.Writer interface.
I was using the value instead of a pointer. If you are using a value instead of a pointer in your structs try using a pointer and see if that fixes the issue for you.
type HtmlRewriter struct {
buf *bytes.Buffer
}
func (w HtmlRewriter) Write(p []byte) (n int, err error) {
return w.buf.Write(p)
}
I post this here as I couldn't find the answer by googling for 'Golang Byte Buffer Empty' because it's a very specific example of the broader concept of values vs pointers.
Simply put, values are duplicated when passed to functions as parameters or as receivers. This means any changes you made to those values are not applied to the original value.
An example of rendering a collection of posts using golang as a web server with it's built in "net/http" and "html/template" packages. In this example we make use of functions in the template and also render one template inside another.
package main
import (
"html/template"
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
mux := http.NewServeMux()
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
funcs := template.FuncMap{
"Date": func() string { return time.Now().Format("2006-01-02") },
}
layout := initTemplate(template.New("layout"), funcs)
initTemplate(layout.New("post"), funcs)
mux.HandleFunc("/", home(layout))
log.Fatal(server.ListenAndServe())
}
type Post struct {
Title string
Body string
}
func home(layout *template.Template) func(http.ResponseWriter, *http.Request) {
posts := []Post{
Post{Title: "Hello World!", Body: "I need to start coming up with something better to say than hello world."},
Post{Title: "Foo bar", Body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent egestas."},
}
return func(w http.ResponseWriter, r *http.Request) {
err := layout.Execute(w, posts)
if err != nil {
log.Panic(err)
}
}
}
func initTemplate(template *template.Template, funcMap template.FuncMap) *template.Template {
template.Funcs(funcMap)
contents, err := ioutil.ReadFile(template.Name() + ".html.tmpl")
if err != nil {
log.Panic(err)
}
template.Parse(string(contents))
return template
}
There is a bit more going on here compared to the previous example. The two main upgrades are rendering a template within a template, and calling functions in a template.
Templates have a template.FuncMap which is a collection of funcs accessible in the template. We must have the template.FuncMap setup before the template is parsed. In the above code snippet we create a simple template.FuncMap with a single function to return a date string.
We've extracted our template initialisation code into the func initTemplate. The func is called and passed in a new empty template and the template.FuncMap we made earlier. It returns to us a useable *template.Template which we store in layout.
We could use template.ParseFiles and it would save us from having to read the template files explicitly with ioutil.ReadFile but it would name our template as "post.html.tmpl" matching the filename. This makes it a little more clumsy when rendering it by name. I'd prefer {{ template "post" . }} over {{ template "post.html.tmpl" . }}.
The reason we create a new template and pass that into initTemplate instead of creating a template in the func is so that we can reuse it to initialise our layout template and also the post template.
The first template is created with template.New("home") and the second with layout.New("post"). Doing it this way allows us to invoke the "post" template in the "layout" template.
Our func (controller action in rails parlance)home takes a pointer to our layout template, and returns the standard HandlerFunc.
posts := []Post{
Post{Title: "Hello World!", Body: "I need to start coming up with something better to say than hello world."},
Post{Title: "Foo bar", Body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent egestas."},
}
The posts passed into layout.Execute(w, posts) are referenced by '.' in the template, as in {{ range . }}. range loops over the posts, setting dot '.' to each post. We then render the post template passing it each post {{ template "post" . }}.
The post template renders each post. {{ Date }} is how our "Date" func in the funcMap is called. {{ .Title }} prints the posts Title field. I'll leave it up to the reader to work out what {{ .Body }} is doing.
The result isn't any different than our first example(except perhaps a change in font) but it is a step closer to something more useful to run in production.
package main
import (
"html/template"
"log"
"net/http"
)
We've added one package "html/template" to our packages from the last example. This core library in golang gives us the html templates. We don't use any of the features this gives us in this example, but it sets the stage for something later.
Parse the template file we have saved in the same directory as our go file which is named "home.html.tmpl". Store the parsed template as layout and check for errors. You'll often have errors in your templates so make sure to display or panic this error as we have done here.
mux.HandleFunc("/", home(layout))
Pass our newly created template to the home function and register it to the "/" path.
There is a bit going on here if you're new to golang. We've defined a new function home which accepts one argument of type *template.Template (pointer to template.Template). The function home also returns a single argument of type func(http.ResponseWriter, *http.Request), that is, it returns a function which takes two arguments. This is a common function signature in the "net/http" package.
return func(w http.ResponseWriter, r *http.Request) {
Our new function home requires us to return a func, so here we define and return one.
We call Execute(w, nil) on our passed in layout which will write the template to the http.ResponseWriter. Ignore the nil for now, we'll use that later to pass in variables. And as always, grab the error and do something useful with it.
We should call the http.ResponseWriter's WriteHeader function with 200 but golang does this for us if we don't.
That is perhaps a little more than strictly necessary for the most basic web server hello world, but I think it's a more useful example which you can build on.
package main
The first golang file is always package main. It has a function main() which will be run when you type go run hello_world.go.
import (
"log"
"net/http"
)
Import the packages "log" and "net/http" from golang's standard library.
func main() {
Define the main function which will be executed when this program is run.
mux := http.NewServeMux()
Mux is an abbreviation for multiplexing. In our context it is what we register our url paths on, giving it functions to call for each. We create a new http.ServeMux and assign it to the variable mux.
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
Create a server listening on port 8080 and using the mux we created earlier to handle web requests.
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World!"))
})
We register the path "/" on our mux and give it a function to respond to requests with. Now when our server gets a request for the path "/" it will call this function to write the response.
log.Fatal(server.ListenAndServe())
Start the server and log any errors if the server returns one.
Less tech is better, so when reaching for a blog I skipped wordpress and picked up golang. A couple years ago Ruby on Rails was a consideration but using that would push me to use more expensive virtual machines.
Wordpress runs the internet, at least a significant share of it. The wiki page mentions 27.5% of the top 10 million websites as of February 2017 which is impressive. My biggest gripe with Wordpress is how slow and bloated it is.
Ruby is a great technology, it makes for happier devs just like its creator Yukihiro Matsumoto wanted.
I hope to see Ruby help every programmer in the world to be productive, and to enjoy programming, and to be happy. That is the primary purpose of Ruby language.
The simple reason for not using Ruby is its what I use for work, generally, and I want to learn something new.
I could have chosen Elixir, or Rust or Node.js. However I've gone for golang, I read about the creation of golang and it's authors pain points for existing languages. What really stood out to me was the focus on simplicity. Clear and simple syntax with few options to do something in more than one way. Sometimes this means ending up writing more code, but I strongly believe it is worth it.
Here is my blog. It's running the latest golang, paired with Postgresql, running on $5 vultr.com VM's located in 4 different data centres around the world. To find the reader's closest server I use ns1.com's free DNS hosting. SSL certs are issued for free by letsencrypt.org.