[Golang] Add Method to Existing Type in External Package


When I write frontend code in Go (compiled to JavaScript via GopherJS), I want to make my code look like JavaScript code as much as possible. For example, I want to getElementById in Go as follows:

element := Document.GetElementById("elmId")

So I write a Go/GopherJS library [1] to realize my idea:

import (
      "github.com/gopherjs/gopherjs/js"
)

var Document = js.Global.Get("document")

func (o *js.Object) GetElementById(id string) *js.Object {
      return o.Call("getElementById", id)
}

When I compile the code, I get the following error message:

panic: interface conversion: ast.Expr is *ast.SelectorExpr, not *ast.Ident [recovered]
      panic: interface conversion: ast.Expr is *ast.SelectorExpr, not *ast.Ident

After some googling [2] [3] [4], I found that it is impossible to add method to existing type in external package. But good news is that I can still do something similar as follows:

type Object struct {
      *js.Object
}

var Document = &Object{js.Global.Get("document")}

func (o *Object) GetElementById(id string) *Object {
      return &Object{o.Call("getElementById", id)}
}

Here we wrap *js.Object in a new defined type Object in our package [1]. And we can getElementById in Go as follows:

import (
      . "github.com/siongui/godom"
)

element := Document.GetElementById("elmId")

Tested on:

  • Ubuntu Linux 16.10
  • Go 1.7.5

References:

[1](1, 2) GitHub - siongui/godom: Make DOM manipultation in Go as similar to JavaScript as possible. (via GopherJS)
[2]
[3]
[4]How to add new methods to an existing type in go? - Stack Overflow
[5]dom - GopherJS bindings for the JavaScript DOM APIs (GitHub)